• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            2010年8月31日

            The article is from http://www.java-samples.com/showtutorial.php?tutorialid=591

            To set all the bytes in a block of memory to a particular value, use memset(). The function prototype is

            void * memset(void *dest, int c, size_t count);
            

            The argument dest points to the block of memory. c is the value to set, and count is the number of bytes, starting at dest, to be set. Note that while c is a type int, it is treated as a type char. In other words, only the low-order byte is used, and you can specify values of c only in the range 0 through 255.

            Use memset() to initialize a block of memory to a specified value. Because this function can use only a type char as the initialization value, it is not useful for working with blocks of data types other than type char, except when you want to initialize to 0. In other words, it wouldn't be efficient to use memset() to initialize an array of type int to the value 99, but you could initialize all array elements to the value 0. memset() will be demonstrated in program below.

            The memcpy() Function

            memcpy() copies bytes of data between memory blocks, sometimes called buffers. This function doesn't care about the type of data being copied--it simply makes an exact byte-for-byte copy. The function prototype is

            void *memcpy(void *dest, void *src, size_t count);
            

            The arguments dest and src point to the destination and source memory blocks, respectively. count specifies the number of bytes to be copied. The return value is dest. If the two blocks of memory overlap, the function might not operate properly--some of the data in src might be overwritten before being copied. Use the memmove() function, discussed next, to handle overlapping memory blocks. memcpy() will be demonstrated in program below.

            The memmove() Function

            memmove() is very much like memcpy(), copying a specified number of bytes from one memory block to another. It's more flexible, however, because it can handle overlapping memory blocks properly. Because memmove() can do everything memcpy() can do with the added flexibility of dealing with overlapping blocks, you rarely, if ever, should have a reason to use memcpy(). The prototype is

            void *memmove(void *dest, void *src, size_t count);
            

            dest and src point to the destination and source memory blocks, and count specifies the number of bytes to be copied. The return value is dest. If the blocks overlap, this function ensures that the source data in the overlapped region is copied before being overwritten. Sample program below demonstrates memset(), memcpy(), and memmove().

            A demonstration of memset(), memcpy(), and memmove().

            1: /* Demonstrating memset(), memcpy(), and memmove(). */
            2:
            3: #include <stdio.h>
            4: #include <string.h>
            4:
            5: char message1[60] = "Four score and seven years ago ...";
            6: char message2[60] = "abcdefghijklmnopqrstuvwxyz";
            7: char temp[60];
            8:
            9: main()
            10: {
            11:    printf("\nmessage1[] before memset():\t%s", message1);
            12:    memset(message1 + 5, `@', 10);
            13:    printf("\nmessage1[] after memset():\t%s", message1);
            14:
            15:    strcpy(temp, message2);
            16:    printf("\n\nOriginal message: %s", temp);
            17:    memcpy(temp + 4, temp + 16, 10);
            18:    printf("\nAfter memcpy() without overlap:\t%s", temp);
            19:    strcpy(temp, message2);
            20:    memcpy(temp + 6, temp + 4, 10);
            21:    printf("\nAfter memcpy() with overlap:\t%s", temp);
            22:
            23:    strcpy(temp, message2);
            24:    printf("\n\nOriginal message: %s", temp);
            25:    memmove(temp + 4, temp + 16, 10);
            26:    printf("\nAfter memmove() without overlap:\t%s", temp);
            27:    strcpy(temp, message2);
            28:    memmove(temp + 6, temp + 4, 10);
            29:    printf("\nAfter memmove() with overlap:\t%s\n", temp);
            30:
            31: }
            message1[] before memset():     Four score and seven years ago ...
            message1[] after memset():      Four @@@@@@@@@@seven years ago ...
            Original message: abcdefghijklmnopqrstuvwxyz
            After memcpy() without overlap: abcdqrstuvwxyzopqrstuvwxyz
            After memcpy() with overlap:    abcdefefefefefefqrstuvwxyz
            Original message: abcdefghijklmnopqrstuvwxyz
            After memmove() without overlap:        abcdqrstuvwxyzopqrstuvwxyz
            After memmove() with overlap:   abcdefefghijklmnqrstuvwxyz
            

            ANALYSIS: The operation of memset() is straightforward. Note how the pointer notation message1 + 5 is used to specify that memset() is to start setting characters at the sixth character in message1[] (remember, arrays are zero-based). As a result, the 6th through 15th characters in message1[] have been changed to @.

            When source and destination do not overlap, memcpy() works fine. The 10 characters of temp[] starting at position 17 (the letters q through z) have been copied to positions 5 though 14, where the letters e though n were originally located. If, however, the source and destination overlap, things are different. When the function tries to copy 10 characters starting at position 4 to position 6, an overlap of 8 positions occurs. You might expect the letters e through n to be copied over the letters g through p. Instead, the letters e and f are repeated five times.

            If there's no overlap, memmove() works just like memcpy(). With overlap, however, memmove() copies the original source characters to the destination.

            posted @ 2010-08-31 11:06 lhking 閱讀(548) | 評論 (0)編輯 收藏

            2010年6月26日

            Vc++6.0項目遷到vs2005 應該注意的問題
            www.firnow.com    時間 : 2010-06-06  作者:佚名   編輯:壹枝雪糕 點擊:  1176 [ 評論 ]
            -
            -
            綜合 資源 電子書 社區   1.如果MessageBox("aa") 報錯,將其要改成 MessageBox(_TEXT("aa")).我喜歡用MessageBox來調試程序,尤其是在寫腳本時,當你不知道程序有沒有執行該條語句,以及執行完該條語句后某個變量的值發生了什么變化,在該條語句前后各加一個MessageBox(str),一目了然了吧 .

            2.pow(2,10)   要改成  pow((double)2,10)或pow(2.0,10)

                   說明:6.0中用到math.h pow()函數時,有這個原型 double pow(int _X,int _Y) 但如果用VC++ 2005的話,pow()的第一個參數就不能再使用int型態,只能使用float、double、long double,VC++ 2005在編譯時會做type checking,然後就過不了,報error C2668

            3.Itoa方法名要改成  _Itoa_s

            4.error C2440:“static_cast” 無法從“void (__thiscall CChatManagerDlg::* )(WPARAM,LPARAM)”轉換為“LRESULT (__thiscall CWnd::* ),出錯處在ON_MESSAGE(WM_SETPLAY,OnSetPlay)

            解答:將void CVideoBaseView::OnSetPlay(WPARAM wp,LPARAM lp)  改成LRESULT CVideoBaseView::OnSetPlay(WPARAM wp,LPARAM lp){

            LRESULT result = Default();

            //你原來的代碼

            return result;}

            5.找不到MFC80D.DLL

            解決:“工程屬性”->“link”->“manifesto file”->“$(IntDir)\$(TargetFileName).intermediate.manifest” 值     改成    $(IntDir)\$(TargetFileName).manifest

            文章出處:飛諾網(www.firnow.com):http://dev.firnow.com/course/3_program/vc/vc_js/200879/132413.html

            posted @ 2010-06-26 09:22 lhking 閱讀(398) | 評論 (0)編輯 收藏

            2010年6月24日

            根據MSDN的描述,采用如下的代碼來實現阻止關機,結果發現在有的機器上能夠阻止關機,在有的機器上卻不能阻止(雖然能看到彈出的MessageBox,但還來不及反應,馬上就關機了)。(都是WinXP SP2的機器)

            view plaincopy to clipboardprint?
            LRESULT CPreventShutdownDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)  
            {  
                if (WM_QUERYENDSESSION == message)  
                {  
                    AfxMessageBox(_T("呵呵,不許關機!"));  
                    return FALSE;  // 根據MSDN,WM_QUERYENDSESSION 返回FALSE則取消關機  
                }  
             
                return CDialog::WindowProc(message, wParam, lParam);  

            LRESULT CPreventShutdownDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
            {
                if (WM_QUERYENDSESSION == message)
                {
                    AfxMessageBox(_T("呵呵,不許關機!"));
                    return FALSE;  // 根據MSDN,WM_QUERYENDSESSION 返回FALSE則取消關機
                }

                return CDialog::WindowProc(message, wParam, lParam);
            }

            是什么原因在某些機器上無法阻止關機呢?

            回憶關機時經常遇到的場景:

            1. 如果某個進程失去響應,關機的時候會提示"...沒有響應,是否結束"

            2. 使用記事本修改了文檔,在沒有保存的情況下進行關機,普通情況會提示是否進行保存。

            1這種情況不好模擬,但是2是很好模擬的。于是在不能阻止關機的機器上這樣進行測試,發現雖然也彈出了是否保存的對話框,但是還是馬上就關機了。

            果然,和程序無關,應該是機器設置的問題。于是想到了一個很流行的詞:"快速關機"

            到網上google了一下,發現快速關機是通過如下的方式實現的:

            HKEY-CURRENT-USER\Control Panel\Desktop\AutoEndTasks  值為1表示快速關機

                                                                                                    普通情況值為0或這個鍵值不存在

            到不能阻止快速關機的機器上一看,果然這個鍵值為1.

            改為0后再運行程序,就都能阻止關機了。

            【結論】阻止關機需要兩步才能完美的實現,而不僅僅是MSDN中描述的2)

                        1) 在程序中先刪除這個鍵值(HKEY-CURRENT-USER\Control Panel\Desktop\AutoEndTasks)

                        2) 處理 WM_QUERYENDSESSION 時返回FALSE

             

            本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/skyxie/archive/2009/06/09/4255767.aspx

            posted @ 2010-06-24 11:03 lhking 閱讀(2700) | 評論 (1)編輯 收藏

            2010年6月23日

            查看未被delete掉的內存,在輸出窗口中查看
            1
             #define _CRTDBG_MAP_ALLOC
             2 #include <stdlib.h>
             3 #include <crtdbg.h>
             4 #include <windows.h>
             5 
             6 int wmain(vint argc , wchar_t* args[])
             7 {
             8     // 這里運行程序,并在下面的函數調用之前delete掉所有new的東西
             9     _CrtDumpMemoryLeaks();
            10     return 0;
            11 }
            posted @ 2010-06-23 23:14 lhking 閱讀(298) | 評論 (0)編輯 收藏

            要實現對一個程序的進程注入,然后對被注入的進程進行控制,首先需要查找到要注入的進程ID。如何獲取的進程ID呢?windows提供了一個API只要知道了這個進程里面的一個窗口句柄,就可以找到找到該進程ID。函數形式如下:DWORD GetWindowThreadProcessId(
              HWND hWnd,
              LPDWORD lpdwProcessId
            );

            那如何獲取這個窗口的句柄呢?很自然我們可以想到這么一個函數,函數形式如下:

            HWND FindWindowEx(     
                HWND hwndParent,
                HWND hwndChildAfter,
                LPCTSTR lpszClass,
                LPCTSTR lpszWindow
            );

            hwndParent:指向一個待搜索窗口的父窗。

            hwndChildAfter:子窗口的句柄。

            lpszClass:窗口的類名。

            lpszWindow:窗口的標題名。

            例如,本示例工程要找到一個對話框里的編輯框,并對這個編輯框進行注入。查找過程如下:

                HWND hWndChild = NULL;
                while(1)
                {
                    // 查找對話框窗口,且這個對話框窗口的標題名為“TestDlg”
                    HWND hDlg = FindWindowEx(0, NULL, "#32770", "TestDlg");
                    if(hDlg == NULL)
                    {
                        printf("沒有找到該對話框窗口!\n");
                        exit(1);
                    }
                    else
                    {
                        // 查找這個對話框窗口中的edit控件
                        hWndChild = FindWindowEx(hDlg, NULL, "Edit",NULL);
                        if(hWndChild != NULL)
                        {
                            break; // 找到這個編輯框,現在要對這個編輯框進行注入
                        }
                    }
                }

                // 根據查找出的窗口,查詢進程
                DWORD dwQQGameId;
                HANDLE hProcessQQGame;
                if(!GetWindowThreadProcessId(hWndChild,&dwQQGameId))
                {
                    printf("Error in GetWindowThreadProcessId():%d\n",GetLastError());
                    exit(1);
                }
            找到這個進程后,然后就要對這個進程進行注入。但是,你別忘記了,當你在其他進程中獲取另外進程的窗口句柄,你是沒有辦法操作這個句柄的。為什么呢?每個進程都被賦予它自己的虛擬地址空間。對于3 2位進程來說,這個地址空間是4 G B,因
            為3 2位指針可以擁有從0 x 0 0 0 0 0 0 0 0至0 x F F F F F F F F之間的任何一個值。這使得一個指針能夠擁有4 294 967 296個值中的一個值,它覆蓋了一個進程的4 G B虛擬空間的范圍。對于6 4位進程來說,這個地址空間是1 6 E B(1 01 8字節),因為6 4位指針可以擁有從0 x 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0至0 x F F F F F F F F F F F F F F F F之間的任何值。這使得一個指針可以擁有18 446 744 073 709 551 616個值中的一個值,它覆蓋了一個進程的1 6 E B虛擬空間的范圍。這是相當大的一個范圍。由于每個進程可以接收它自己的私有的地址空間,因此當進程中的一個線程正在運行時,該線程可以訪問只屬于它的進程的內存。屬于所有其他進程的內存則隱藏著,并且不能被正在運行的線程訪問。注意在Windows 2000中,屬于操作系統本身的內存也是隱藏的,正在運行的線程無法訪問。這意味著線程常常不能訪問操作系統的數據。Windows 98中,屬于操作系統的內存是不隱藏的,正在運行的線程可以訪問。因此,正在運行的線程常常可以訪問操作系統的數據,也可以破壞操作系統(從而有可能導致操作系統崩潰)。在Windows 98中,一個進程的線程不可能訪問屬于另一個進程的內存。前面說過,每個進程有它自己的私有地址空間。進程A可能有一個存放在它的地址空間中的數據結構,地址是0 x 1 2 3 4 5 6 7 8,而進程B則有一個完全不同的數據結構存放在它的地址空間中,地址是0 x 1 2 3 4 5 6 7 8。當進程A中運行的線程訪問地址為0 x 1 2 3 4 5 6 7 8的內存時,這些線程訪問的是進程A的數據結構。當進程B中運行的線程訪問地址為0 x 1 2 3 4 5 6 7 8的內存時,這些線程訪問的是進程B的數據結構。進程A中運行的線程不能訪問進程B的地址空間中的數據結構,反之亦然。

            這樣看來,若想對這個窗口句柄進行操作,得想方設法使我們能夠進入到原宿主進程中,然后執行我們的操作。這個就好象一個寄生蟲想要破壞人體的機能,必須得進入我們的體內,寄生在我們的組織上才能夠產生作用。現在關鍵是如何寄生到宿主中呢?

            通常,任何進程都可以通過LoadLibrary動態地加載DLL,但是我們如何強制一個外部進程調用該函數呢?答案是CreateRemoteThread。
            讓我們先來看看LoadLibrary和FreeLibrary的函數聲明:

            HINSTANCE LoadLibrary(
              LPCTSTR lpLibFileName   // address of filename of library module
            );

            BOOL FreeLibrary(
              HMODULE hLibModule      // handle to loaded library module
            );

            再和CreateRemoteThread的線程過程(thread procedure)ThreadProc比較一下:
            DWORD WINAPI ThreadProc(
              LPVOID lpParameter   // thread data
            );

                你會發現所有的函數都有同樣的調用約定(calling convention)、都接受一個32位的參數并且返回值類型的大小也一樣。也就是說,我們可以把LoadLibrary/FreeLibrary的指針作為參數傳遞給CrateRemoteThread。

                然而,還有兩個問題(參考下面對CreateRemoteThread的說明)

                1. 傳遞給ThreadProc的lpStartAddress 參數必須為遠程進程中的線程過程的起始地址。
                2. 如果把ThreadProc的lpParameter參數當做一個普通的32位整數(FreeLibrary把它當做HMODULE)那么沒有如何問題,但是如果把它當做一個指針(LoadLibrary把它當做一個char*),它就必須指向遠程進程中的內存數據。

                第一個問題其實已經迎刃而解了,因為LoadLibrary和FreeLibrary都是存在于kernel32.dll中的函數,而kernel32可以保證任何“正常”進程中都存在,且其加載地址都是一樣的。(參看附錄A)于是LoadLibrary/FreeLibrary在任何進程中的地址都是一樣的,這就保證了傳遞給遠程進程的指針是個有效的指針。

                第二個問題也很簡單:把DLL的文件名(LodLibrary的參數)用WriteProcessMemory復制到遠程進程。

                所以,使用CreateRemoteThread和LoadLibrary技術的步驟如下:
                1. 得到遠程進程的HANDLE(使用OpenProcess)。
                2. 在遠程進程中為DLL文件名分配內存(VirtualAllocEx)。
                3. 把DLL的文件名(全路徑)寫到分配的內存中(WriteProcessMemory)
                4. 使用CreateRemoteThread和LoadLibrary把你的DLL映射近遠程進程。
                5. 等待遠程線程結束(WaitForSingleObject),即等待LoadLibrary返回。也就是說當我們的DllMain(是以DLL_PROCESS_ATTACH為參數調用的)返回時遠程線程也就立即結束了。
                6. 取回遠程線程的結束碼(GetExitCodeThtread),即LoadLibrary的返回值――我們DLL加載后的基地址(HMODULE)。
                7. 釋放第2步分配的內存(VirtualFreeEx)。
                8. 用CreateRemoteThread和FreeLibrary把DLL從遠程進程中卸載。調用時傳遞第6步取得的HMODULE給FreeLibrary(通過CreateRemoteThread的lpParameter參數)。
                9. 等待線程的結束(WaitSingleObject)。

            主要代碼如下:

            #include<stdio.h>
            #include<conio.h>
            #include<windows.h>

            void main()
            {
                HWND hWndChild = NULL;
                while(1)
                {
                    // 查找對話框窗口,且這個對話框窗口的標題名為“TestDlg”
                    HWND hDlg = FindWindowEx(0, NULL, "#32770", "TestDlg");
                    if(hDlg == NULL)
                    {
                        printf("沒有找到該對話框窗口!\n");
                        exit(1);
                    }
                    else
                    {
                        // 查找這個對話框窗口中的edit控件
                        hWndChild = FindWindowEx(hDlg, NULL, "Edit",NULL);
                        if(hWndChild != NULL)
                        {
                            break; // 找到這個編輯框,現在要對這個編輯框進行注入
                        }
                    }
                }

                // 根據查找出的窗口,查詢進程
                DWORD dwQQGameId;
                HANDLE hProcessQQGame;
                if(!GetWindowThreadProcessId(hWndChild,&dwQQGameId))
                {
                    printf("Error in GetWindowThreadProcessId():%d\n",GetLastError());
                    exit(1);
                }


                HINSTANCE hDll = NULL;
                typedef void(*LP_SET_HEDIT_FUN)(HWND);
                LP_SET_HEDIT_FUN m_SethEdit = NULL;
                char DllPath[MAX_PATH] = "D:\\進程注入測試工程\\Bin\\automessagedll.dll";
                hDll = LoadLibrary(DllPath);
                if(hDll)
                {
                    m_SethEdit = (LP_SET_HEDIT_FUN)GetProcAddress(hDll,"SethEdit");
                }
                if(m_SethEdit)
                {
                    m_SethEdit(hWndChild);
                }
                else
                {
                    printf("Can not load SethEdit in the dll(%d).\n",GetLastError());
                }

             

                if( (hProcessQQGame = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwQQGameId)) == NULL)
                {
                    printf("Error in OpenProcess():%d\n",GetLastError());
                    getch();
                    exit(1);
                }

                int cb = (1+lstrlen(DllPath))* sizeof(char);

                char* RemoteLibFile = (char*)VirtualAllocEx(hProcessQQGame,NULL,cb,MEM_COMMIT,PAGE_READWRITE);
                if(RemoteLibFile == NULL)
                {
                    printf("Error in VirtualAllocEx():%d\n",GetLastError());
                    getch();
                    exit(1);
                }
                if( (WriteProcessMemory(hProcessQQGame,RemoteLibFile,(LPVOID)DllPath,cb,NULL)) == 0)
                {
                    printf("Error in WriteProcessMemory():%d\n",GetLastError());
                    getch();
                    exit(1);
                }


                PTHREAD_START_ROUTINE pfnStartAddr;
                pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32"),"LoadLibraryA");


                HANDLE hThread = CreateRemoteThread(hProcessQQGame,NULL,0,pfnStartAddr,RemoteLibFile,0,NULL);
                if(hThread == NULL)
                {
                    printf("Error in CreateRemoteThread():%d",GetLastError());
                    getch();
                    exit(1);
                }

                WaitForSingleObject(hThread,INFINITE);


                CloseHandle(hThread);
                VirtualFreeEx(hProcessQQGame,RemoteLibFile,0,MEM_RELEASE);
                CloseHandle(hProcessQQGame);
            }

             

            本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/kissyfish/archive/2008/12/07/3462055.aspx

            posted @ 2010-06-23 15:33 lhking 閱讀(1219) | 評論 (0)編輯 收藏

            下載文件要用到操作系統的API函數,下面是一個WINDOWS系統中的實現:

            //---------------------------------------------------------------------------
            #include "stdafx.h"
            #include <stdio.h>
            #include <windows.h>
            #include <wininet.h>
            #define MAXBLOCKSIZE 1024
            #pragma comment( lib, "wininet.lib" ) ;

            void download(const char *Url,const char *save_as)/*將Url指向的地址的文件下載到save_as指向的本地文件*/
            {
             byte Temp[MAXBLOCKSIZE];
             ULONG Number = 1;

             FILE *stream;
             HINTERNET hSession = InternetOpen(_T("RookIE/1.0"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
             if (hSession != NULL)
             {
              HINTERNET handle2 = InternetOpenUrl(hSession,_T(Url), NULL, 0, INTERNET_FLAG_DONT_CACHE, 0);
              if (handle2 != NULL)
              {


               if( (stream = fopen( save_as, "wb" )) != NULL )
               {
                while (Number > 0)
                {
                 InternetReadFile(handle2, Temp, MAXBLOCKSIZE - 1, &Number);

                 fwrite(Temp, sizeof (char), Number , stream);
                }
                fclose( stream );
               }

               InternetCloseHandle(handle2);
               handle2 = NULL;
              }
              InternetCloseHandle(hSession);
              hSession = NULL;
             }
            }

            int main(int argc, char* argv[]){

             download("*調用示例,下載百度的首頁到c:\index.html文件*/
             return 0;
            }

             

            方法一:
            SetTimer(NULL, 0, 1000, (TIMERPROC)Timer2Proc);

            VOID CALLBACK Timer2Proc(
                   HWND hWnd, // handle of window for timer messages
                   UINT uMsg, // WM_TIMER message
                   UINT idEvent, // timer identifier
                   DWORD dwTime // current system time
                   )
            {
             return;
            }

            方法二:
            // DLL中的線程函數可以象這樣使用Timer
            UINT ThreadProc(LPVOID)
            {

             SetTimer(NULL, 1, 5000, NULL);
             MSG msg;
             // PeekMessage 強制系統為該線程建立消息棧
             PeekMessage(&msg, NULL, NULL, NULL, FALSE);
             while (GetMessage(&msg, NULL, NULL, NULL))
             {
              switch (msg.message)
              {
              case WM_TIMER:
               {
                // 這里每5秒鐘執行一次
               }
               break;
              }
              //TranslateMessage(&msg);
              //DispatchMessage(&msg);
             }
             KillTimer(NULL, 1);
             return 0;
            }

            方法三:
            創建一個線程, 反復讀系統時間不就可以了? 如果定時要求不嚴,用Sleep就可以了
            UINT TimerThread(LPVOID pama)
            {
             UINT oldTickCount, newTickCount;
             oldTickCount = GetTickCount();
             while(TRUE)
             {
              while(TRUE)
              {
               newTickCount = GetTickCount();
               if(newTickCount - oldTickCount >= 100)
               {
                oldTickCount = newTickCount;
                break;
               }
              }
              TimeProc();
             }
             return 0;
            }
            大約每100ms 調用一次TimeProc();

            posted @ 2010-06-23 14:57 lhking 閱讀(3022) | 評論 (0)編輯 收藏

            2010年6月22日

            MFC is basicly a library of OO wrapper classes that wrap the Win32 api, and provide objects for the basic window components (windows, buttons, checkboxes etc..). Essentially it is the win32 api objectified.

            Also MFC provides some classes that resemble classes found in the STL. As MFC was made before STL was fully standardised.

            My knowledge is incomplete. But that is the basic Idea.



             User Rating: 1019   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

            The difference between Win32 and MFC are pretty straightforward:

            The Windows API (Win32) uses a C interface to access windows functionality. It requires that you write all of your own code to manage windows and message handling. It is quite straightforward but you will need a good reference, like MSDN, and some good tutorials or samples to get started.

            In contrast, MFC, which stands for Microsoft Foundation Classes, are a collection of C++ classes which encapsulate the Win32 API. MFC has some wizards which make the initial creation of a program quick and easy, but I have to admit the learning curve of MFC can sometimes be frustrating as Microsoft seems to have done everything in a way that can at times seem counter-intuitive.

            Whenever I write an application I write it in MFC but I have been writing applications in MFC for a long time. If all you want is a message loop and a window handle for a game, use Win32. If you want to write a larger application like an editor, maybe MFC is the right tool.

            Ideally, I would suggest skipping both Win32 and MFC and writing tools in .NET. I do not have any personal experience in it but people I work with sure can get a lot done using it. It may well be worth investigation.

            Best of luck,

            - S

             User Rating: 1352   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

            Quote:
            Original post by Sphet

            Whenever I write an application I write it in MFC but I have been writing applications in MFC for a long time. If all you want is a message loop and a window handle for a game, use Win32. If you want to write a larger application like an editor, maybe MFC is the right tool.

            - S


            I am planning to write an interactive 3D environment does that mean using WIN32 application is a better tool for it?

            also is it possible to use openGL for oject creation and DirectXinput for the interactive control?
            please give me some suggestion



            millions of thanks

             User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

            Quote:
            Original post by muimui1911
            I am planning to write an interactive 3D environment does that mean using WIN32 application is a better tool for it?

            For a game Win32 is usually better.
            I think I have also heard that MFC doesn't work well in fullscreen.

            Quote:
            Original post by muimui1911
            also is it possible to use openGL for oject creation and DirectXinput for the interactive control?

            You can render with opengl and use directinput for input.

            ____________________________________________________________
            Programmers Resource Central

             User Rating: 1107   |  Rate This User  Send Private MessageView ProfileView GD Showcase Entries Report this Post to a Moderator | Link

            what about mouse movement like shooting games?

            how can i do that, please give me some direction

             User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

            You can use directinput for mouse movement. Or you can use GetCursorPos(POINT *p);

            ____________________________________________________________
            Programmers Resource Central

             User Rating: 1107   |  Rate This User  Send Private MessageView ProfileView GD Showcase Entries Report this Post to a Moderator | Link

            How do i use that? can you give me some example and much clearer direction

            millions of thanks

             User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

            msdn
            Though if you want a camera class look here and here.
            posted @ 2010-06-22 11:43 lhking 閱讀(339) | 評論 (0)編輯 收藏

            2010年6月21日

            對于眾多人提出的c/c++中指針難學的問題做個總結:

              指針學習不好關鍵是概念不清造成的,說的簡單點就是書沒有認真看,指針的學習猶如人在學習饒口令不多看多學多練是不行的,下面是兩個很經典的例子,很多書上都有,對于學習的重點在于理解*x和x的理解,他們并不相同,*x所表示的其實就是變量a本身,x表示的是變量a在內存中的地址,如果想明白可以輸出觀察cout<<*x"|"x;,當定義了int *x;后對x=&a的理解的問題。仔細閱讀和聯系下面的兩個例子我想指針問題就不是難點了!

            #include <stdio.h>

            main()
            {
            int a,b; /* 定義a,b兩個整形變量用于輸入兩個整數 */
            int *point_1,*point_2,*temp_point; /* 定義三個指針變量 */
            scanf("%d,%d",&a,&b); /* 格式化輸入a,b的值 */
            point_1=&a; /* 把指針變量point_1的值指向變量a的地址 */
            point_2=&b; /* 把指針變量point_2的值指向變量b的地址 */
            if (a<b)
            {
                 temp_point=point_1; /* 這里的temp_point是用于臨時存儲point_1的值也就是變量a的地址的 */
                 point_1=point_2; /* 把point_2的值賦予point_1 */
                 point_2=temp_point;
                 /* 由于point_1的值已經改變無法找到,利用前面臨時存儲的也就是temp_point找回原point_1的值賦予point_2,打到把point_1和point_2值對換的目的*/
            }
            printf("%d,%d",*point_1,*point_2); /* 利用*point_1和*point_2也就是分辨指向b和a的方法把值顯示自愛屏幕上 */
            }

            /* 此題需要注意和了解是的此法并沒有改變變量a,b的值只是利用指針變量分別存儲a和b的地址,然后再把那兩個指針變量的值對換一下其實就是存儲在
            指針變量里面a與b的地址對換,在利用*point_1和*point_2的方式把調換后的值顯示出來這里的*point_1實際就是a,此中算法并非真的改變a,b的值,而是
            利用指針進行地址交換達到大小排序的目的.
            */



            #include <stdio.h>

            main()
            {
            int a,b; /* 定義a,b兩個整形變量用于輸入兩個整數 */
            int *point_1,*point_2; /* 定義三個指針變量 */
            scanf("%d,%d",&a,&b); /* 格式化輸入a,b的值 */
            point_1 = &a; /* 把指針變量point_1的值指向變量a的地址 */
            point_2 = &b; /* 把指針變量point_2的值指向變量b的地址 */
            compositor(point_1,point_2); /* 調用自定義的排序涵數,把a,b的地址傳遞給point_1和point_2 */
            printf("%d,%d",a,b); /* 打印出a,b的值 */
            }

            static compositor(p1,p2)
            int *p1,*p2; /* 定義形式參數p1,p2為指針變量 */
            {
            int temp; /* 建立臨時存儲變量 */
                 if (*p1<*p2) /* 如果*p1<p2,注意這里的*p1和*p2其實就是a和b */
                 {
                     temp = *p1; /* 利用變量temp用于臨時存儲*p1和就是a的值 */
                     *p1 = *p2; /* 將*p1的值也就是a的值換成*p2的值也就是b的值,等價于a=b */
                     *p2 = temp; /* 將*p2的值也就是temp的值等價于b=temp */
                 }
            }

            /* 注意:此題與上題不同的是,直接改變了a于b的值達到真實改變的目的 */

            posted @ 2010-06-21 23:02 lhking 閱讀(238) | 評論 (0)編輯 收藏
            VC常用數據類型轉換詳解
            我們先定義一些常見類型變量借以說明
            int i = 100;
            long l = 2001;
            float f=300.2;
            double d=12345.119;
            char username[]="程佩君";
            char temp[200];
            char *buf;
            CString str;
            _variant_t v1;
            _bstr_t v2;
            一、其它數據類型轉換為字符串

            短整型(int)
            itoa(i,temp,10);///將i轉換為字符串放入temp中,最后一個數字表示十進制
            itoa(i,temp,2); ///按二進制方式轉換
            長整型(long)
            ltoa(l,temp,10);
            浮點數(float,double)
            用fcvt可以完成轉換,這是MSDN中的例子:
            int decimal, sign;
            char *buffer;
            double source = 3.1415926535;
            buffer = _fcvt( source, 7, &decimal, &sign );
            運行結果:source: 3.1415926535 buffer: '31415927' decimal: 1 sign: 0
            decimal表示小數點的位置,sign表示符號:0為正數,1為負數
            CString變量
            str = "2008北京奧運";
            buf = (LPSTR)(LPCTSTR)str;
            BSTR變量
            BSTR bstrValue = ::SysAllocString(L"程序員");
            char * buf = _com_util::ConvertBSTRToString(bstrValue);
            SysFreeString(bstrValue);
            AfxMessageBox(buf);
            delete(buf);
            CComBSTR變量
            CComBSTR bstrVar("test");
            char *buf = _com_util::ConvertBSTRToString(bstrVar.m_str);
            AfxMessageBox(buf);
            delete(buf);
            _bstr_t變量
            _bstr_t類型是對BSTR的封裝,因為已經重載了=操作符,所以很容易使用
            _bstr_t bstrVar("test");
            const char *buf = bstrVar;///不要修改buf中的內容
            AfxMessageBox(buf);

            通用方法(針對非COM數據類型)
            用sprintf完成轉換
            char buffer[200];
            char c = '1';
            int   i = 35;
            long j = 1000;
            float f = 1.7320534f;
            sprintf( buffer, "%c",c);
            sprintf( buffer, "%d",i);
            sprintf( buffer, "%d",j);
            sprintf( buffer, "%f",f);
            二、字符串轉換為其它數據類型
            strcpy(temp,"123");
            短整型(int)
            i = atoi(temp);
            長整型(long)
            l = atol(temp);
            浮點(double)
            d = atof(temp);
            CString變量
            CString name = temp;
            BSTR變量
            BSTR bstrValue = ::SysAllocString(L"程序員");
            ...///完成對bstrValue的使用
            SysFreeString(bstrValue);
            CComBSTR變量
            CComBSTR類型變量可以直接賦值
            CComBSTR bstrVar1("test");
            CComBSTR bstrVar2(temp);
            _bstr_t變量
            _bstr_t類型的變量可以直接賦值
            _bstr_t bstrVar1("test");
            _bstr_t bstrVar2(temp);

            三、其它數據類型轉換到CString
            使用CString的成員函數Format來轉換,例如:

            整數(int)
            str.Format("%d",i);
            浮點數(float)
            str.Format("%f",i);
            字符串指針(char *)等已經被CString構造函數支持的數據類型可以直接賦值
            str = username;
            對于Format所不支持的數據類型,可以通過上面所說的關于其它數據類型轉化到char *的方法先轉到char *,然后賦值給CString變量。
            四、BSTR、_bstr_t與CComBSTR

            CComBSTR 是ATL對BSTR的封裝,_bstr_t是C++對BSTR的封裝,BSTR是32位指針,但并不直接指向字串的緩沖區。
            char *轉換到BSTR可以這樣:
            BSTR b=_com_util::ConvertStringToBSTR("數據");///使用前需要加上comutil.h和comsupp.lib
            SysFreeString(bstrValue);
            反之可以使用
            char *p=_com_util::ConvertBSTRToString(b);
            delete p;
            具體可以參考一,二段落里的具體說明。
            CComBSTR與_bstr_t對大量的操作符進行了重載,可以直接進行=,!=,==等操作,所以使用非常方便。
            特別是_bstr_t,建議大家使用它。

            五、VARIANT 、_variant_t 與 COleVariant

            VARIANT的結構可以參考頭文件VC98\Include\OAIDL.H中關于結構體tagVARIANT的定義。
            對于VARIANT變量的賦值:首先給vt成員賦值,指明數據類型,再對聯合結構中相同數據類型的變量賦值,舉個例子:
            VARIANT va;
            int a=2001;
            va.vt=VT_I4;///指明整型數據
            va.lVal=a; ///賦值
            對于不馬上賦值的VARIANT,最好先用Void VariantInit(VARIANTARG FAR* pvarg);進行初始化,其本質是將vt設置為VT_EMPTY,下表我們列舉vt與常用數據的對應關系:
            Byte bVal; // VT_UI1.
            Short iVal; // VT_I2.
            long lVal; // VT_I4.
            float fltVal; // VT_R4.
            double dblVal; // VT_R8.
            VARIANT_BOOL boolVal; // VT_BOOL.
            SCODE scode; // VT_ERROR.
            CY cyVal; // VT_CY.
            DATE date; // VT_DATE.
            BSTR bstrVal; // VT_BSTR.
            DECIMAL FAR* pdecVal // VT_BYREF|VT_DECIMAL.
            IUnknown FAR* punkVal; // VT_UNKNOWN.
            IDispatch FAR* pdispVal; // VT_DISPATCH.
            SAFEARRAY FAR* parray; // VT_ARRAY|*.
            Byte FAR* pbVal; // VT_BYREF|VT_UI1.
            short FAR* piVal; // VT_BYREF|VT_I2.
            long FAR* plVal; // VT_BYREF|VT_I4.
            float FAR* pfltVal; // VT_BYREF|VT_R4.
            double FAR* pdblVal; // VT_BYREF|VT_R8.
            VARIANT_BOOL FAR* pboolVal; // VT_BYREF|VT_BOOL.
            SCODE FAR* pscode; // VT_BYREF|VT_ERROR.
            CY FAR* pcyVal; // VT_BYREF|VT_CY.
            DATE FAR* pdate; // VT_BYREF|VT_DATE.
            BSTR FAR* pbstrVal; // VT_BYREF|VT_BSTR.
            IUnknown FAR* FAR* ppunkVal; // VT_BYREF|VT_UNKNOWN.
            IDispatch FAR* FAR* ppdispVal; // VT_BYREF|VT_DISPATCH.
            SAFEARRAY FAR* FAR* pparray; // VT_ARRAY|*.
            VARIANT FAR* pvarVal; // VT_BYREF|VT_VARIANT.
            void FAR* byref; // Generic ByRef.
            char cVal; // VT_I1.
            unsigned short uiVal; // VT_UI2.
            unsigned long ulVal; // VT_UI4.
            int intVal; // VT_INT.
            unsigned int uintVal; // VT_UINT.
            char FAR * pcVal; // VT_BYREF|VT_I1.
            unsigned short FAR * puiVal; // VT_BYREF|VT_UI2.
            unsigned long FAR * pulVal; // VT_BYREF|VT_UI4.
            int FAR * pintVal; // VT_BYREF|VT_INT.
            unsigned int FAR * puintVal; //VT_BYREF|VT_UINT.

            _variant_t是VARIANT的封裝類,其賦值可以使用強制類型轉換,其構造函數會自動處理這些數據類型。
            使用時需加上#include <comdef.h>
            例如:
            long l=222;
            ing i=100;
            _variant_t lVal(l);
            lVal = (long)i;

            COleVariant的使用與_variant_t的方法基本一樣,請參考如下例子:
            COleVariant v3 = "字符串", v4 = (long)1999;
            CString str =(BSTR)v3.pbstrVal;
            long i = v4.lVal;

            六、其它一些COM數據類型
            根據ProgID得到CLSID
            HRESULT CLSIDFromProgID( LPCOLESTR lpszProgID,LPCLSID pclsid);
            CLSID clsid;
            CLSIDFromProgID( L"MAPI.Folder",&clsid);
            根據CLSID得到ProgID
            WINOLEAPI ProgIDFromCLSID( REFCLSID clsid,LPOLESTR * lplpszProgID);
            例如我們已經定義了 CLSID_IApplication,下面的代碼得到ProgID
            LPOLESTR pProgID = 0;
            ProgIDFromCLSID( CLSID_IApplication,&pProgID);
            ...///可以使用pProgID
            CoTaskMemFree(pProgID);//不要忘記釋放
            七、ANSI與Unicode
            Unicode稱為寬字符型字串,COM里使用的都是Unicode字符串。
            將ANSI轉換到Unicode
            (1)通過L這個宏來實現,例如: CLSIDFromProgID( L"MAPI.Folder",&clsid);
            (2)通過MultiByteToWideChar函數實現轉換,例如:
            char *szProgID = "MAPI.Folder";
            WCHAR szWideProgID[128];
            CLSID clsid;
            long lLen = MultiByteToWideChar(CP_ACP,0,szProgID,strlen(szProgID),szWideProgID,sizeof(szWideProgID));
            szWideProgID[lLen] = '\0';
            (3)通過A2W宏來實現,例如:
            USES_CONVERSION;
            CLSIDFromProgID( A2W(szProgID),&clsid);
            將Unicode轉換到ANSI
            (1)使用WideCharToMultiByte,例如:
            // 假設已經有了一個Unicode 串 wszSomeString...
            char szANSIString [MAX_PATH];
            WideCharToMultiByte ( CP_ACP, WC_COMPOSITECHECK, wszSomeString, -1, szANSIString, sizeof(szANSIString), NULL, NULL );
            (2)使用W2A宏來實現,例如:
            USES_CONVERSION;
            pTemp=W2A(wszSomeString);
            八、其它
            對消息的處理中我們經常需要將WPARAM或LPARAM等32位數據(DWORD)分解成兩個16位數據(WORD),例如:
            LPARAM lParam;
            WORD loValue = LOWORD(lParam);///取低16位
            WORD hiValue = HIWORD(lParam);///取高16位

            對于16位的數據(WORD)我們可以用同樣的方法分解成高低兩個8位數據(BYTE),例如:
            WORD wValue;
            BYTE loValue = LOBYTE(wValue);///取低8位
            BYTE hiValue = HIBYTE(wValue);///取高8位

            兩個16位數據(WORD)合成32位數據(DWORD,LRESULT,LPARAM,或WPARAM)
            LONG MAKELONG( WORD wLow, WORD wHigh );
            WPARAM MAKEWPARAM( WORD wLow, WORD wHigh );
            LPARAM MAKELPARAM( WORD wLow, WORD wHigh );
            LRESULT MAKELRESULT( WORD wLow, WORD wHigh );

            兩個8位的數據(BYTE)合成16位的數據(WORD)
            WORD MAKEWORD( BYTE bLow, BYTE bHigh );

            從R(red),G(green),B(blue)三色得到COLORREF類型的顏色值
            COLORREF RGB( BYTE byRed,BYTE byGreen,BYTE byBlue );
            例如COLORREF bkcolor = RGB(0x22,0x98,0x34);

            從COLORREF類型的顏色值得到RGB三個顏色值
            BYTE Red = GetRValue(bkcolor); ///得到紅顏色
            BYTE Green = GetGValue(bkcolor); ///得到綠顏色
            BYTE Blue = GetBValue(bkcolor); ///得到蘭顏色

            九、注意事項
            假如需要使用到ConvertBSTRToString此類函數,需要加上頭文件comutil.h,并在setting中加入comsupp.lib或者直接加上#pragma comment( lib, "comsupp.lib" )

            posted @ 2010-06-21 22:59 lhking 閱讀(305) | 評論 (0)編輯 收藏
            僅列出標題  下一頁

            導航

            <2011年10月>
            2526272829301
            2345678
            9101112131415
            16171819202122
            23242526272829
            303112345

            統計

            常用鏈接

            留言簿

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            国产精品天天影视久久综合网| 日韩十八禁一区二区久久| 久久久久成人精品无码中文字幕 | 1000部精品久久久久久久久| AAA级久久久精品无码片| 色综合久久精品中文字幕首页| 久久成人精品| 99久久国产宗和精品1上映| 国产精品天天影视久久综合网| 久久精品国产一区二区| 亚洲性久久久影院| 精品久久久久久无码专区| 久久精品国产99国产精品| 国产成人久久精品一区二区三区| 国产成人久久777777| 久久亚洲国产成人精品性色| 狠狠精品干练久久久无码中文字幕| 久久人妻AV中文字幕| 久久强奷乱码老熟女| 国内精品人妻无码久久久影院 | 狠狠色综合网站久久久久久久| 欧美激情一区二区久久久| 国产亚洲色婷婷久久99精品91| 色婷婷综合久久久久中文一区二区 | 久久久久久综合网天天| 国产99久久久久久免费看| 精品国产乱码久久久久久1区2区| 伊人 久久 精品| 青青草原综合久久大伊人导航| 中文精品久久久久国产网址 | 久久久精品国产亚洲成人满18免费网站| 综合网日日天干夜夜久久| 久久久久免费视频| 日本久久久久久中文字幕| 国产午夜福利精品久久2021 | 国产69精品久久久久APP下载| 国产成人精品久久综合| www亚洲欲色成人久久精品| 亚洲伊人久久大香线蕉苏妲己| 99久久99这里只有免费费精品| 漂亮人妻被黑人久久精品|