• <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>

            朗朗空間

            我知道并不是 所有鳥兒都飛翔

              C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
              16 Posts :: 0 Stories :: 6 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(1)

            我參與的團隊

            搜索

            •  

            最新隨筆

            最新評論

            閱讀排行榜

            評論排行榜

            來自:http://www.relisoft.com/win32/winnie.html
            譯:聶元朗
            1. The Simplest Windows Program
            1.最簡單的Windows程序

            Before you can even begin thinking about programming in Windows, you have to be able to understand how this simple program works.

            在你開始想如何在windows下編程之前,你必須要弄清楚下面這個簡單windows程序的工作原理。

            Windows API calls are highlighted in blue and Windows specific data types are shown in green. I will also usually put a double colon in front of API calls. In C++, that simply means that I'm calling a global function, in case there is some ambiguity.

            我用藍色來標識Windows的API調用,用綠色來標識Windows中的特殊的數據類型。同時我在API函數的前面放置了一對冒號::。在C++中,這對冒號就是告訴編譯器我在調用一個全局函數。由于有時候有同名的函數,為了不引起混淆,在前面放置冒號是一種很好的做法

            Sources (zipped file 4k) are right here. Remember to compile them as a Windows application. For instance, in Visual C++ select File.New.Projects.Win32 Application. Otherwise you'll get the error: unresolved external _main. (I provided project file Winnie.dsp for those of you who use MS VC++ 6.0 and Winnie.sln for the users of VC++ 7.0)

            我提供了源代碼(一個4k大小的壓縮文件)。請記住要把它們編譯成一個windows應用程序而不是windows控制臺程序。否則,你就會得到找不到main函數的錯誤。在VC++6.0中,我們可以通過選擇File——New Projects——Win32 Application來創建一個windows應用程序的工程。當然,你用不著這么擔心,我已經提供了兩個做好的工程文件給你。一個是winnie.dsp,你可以在VC++6.0下使用。一個是Winnie.sln,你可以在VC++7.0下使用。

            First, in a Windows program, you have to define a Window Class, the "class" of window(s) that will be displayed by your application (not a C++ class). In our case we will display only one window, but still, we need to give Windows some minimal information about its Class. The most important part of the WinClass (now, that's a C++ class that describes the Window Class) is the address of the callback procedure, or the Window Procedure. Windows is supposed to call us--Windows sends messages to our program by calling this procedure.

            好了,讓我們來看看如何寫這個最簡單的程序吧。首先,在一個windows程序里面,你需要定義一個窗口類,注意這個類的概念不同于C++中的類,這個窗口類相當于C語言中的結構體,你把這個結構體填好了,然后你的應用程序就會根據你填的這些信息來顯示窗口。在我們的例子里面,我們僅僅顯示一個窗口。但是就算是這樣,我們也必須要給我們的窗口最少的窗口類信息。而其中最重要的部分就是回調函數了,有時候我們也稱它為窗口過程。其實這是一個函數指針,每次程序需要處理消息的時候,windows就通過這個函數指針來調用我們寫好的回調函數。是的,你看到,是windows調用我們編寫的函數。你還記得函數指針嗎?如果不是很清楚,可以google一下,o(∩_∩)o…

            Notice the declaration of WindowProcedure. Windows calls it with a handle to the window in question, the message, and two data items associated with the message, the paramters, WPARAM and LPARAM.

            讓我們看看WindowProcedure(窗口過程、回調函數)的定義。仔細看一下,第一個函數是一個句柄,也就是個整數。Windows用它來區別是哪個窗口。然后是消息,然后是與消息關系密切的兩個參數WPARAM和LPARAM。這個我本來想講一下,留到以后吧,畢竟原文中在這里沒有講。

            In WinClass we also have to specify things like the program instance handle HINSTANCE, the mouse cursor (we just load the standard arrow cursor), the brush to paint the window's background (we chose the default window color brush), and the symbolic name of our class (you don't have to understand the meaning of all those yet).

            在下面的WinClass類中我們必須給一些窗口類的字段賦值,如窗口的實例句柄HINSTACE,鼠標光標(我們僅僅加載了標準的箭頭鼠標),畫窗口背景的畫刷(我們用的是窗口缺省的背景顏色畫刷),最后還有窗口類的名字(窗口類的名字最好和別人的不同).(當然,現在你不需要弄明白這些參數的意義)

            Once all the fields of WNDCLASS are filled, we register the class with the Windows system.

            一旦我們把WNDCLASS結構體填完了,我們就通過調用RegisterClass函數在windows系統中注冊我們的窗口類。好了,先看看我是怎樣封裝WNDCLASS到一個WinClass類中去的。

            #include <windows.h>
            LRESULT CALLBACK WindowProcedure
                (HWND hwnd, unsigned int message, WPARAM wParam, LPARAM lParam);
            class WinClass
            {
            public:
                WinClass (WNDPROC winProc, char const * className, HINSTANCE hInst);
                void Register ()
                {
                    ::RegisterClass (&_class);//now we don’t deal with the error
                }//we will process the error in the next version
            private:
                WNDCLASS _class;//define a private WNDCLASS object member
            };
            
            WinClass::WinClass
                (WNDPROC winProc, char const * className, HINSTANCE hInst)
            {
                _class.style = 0;
                _class.lpfnWndProc = winProc; // window procedure: mandatory
                _class.cbClsExtra = 0;
                _class.cbWndExtra = 0;
                _class.hInstance = hInst;         // owner of the class: mandatory
                _class.hIcon = 0;
                _class.hCursor = ::LoadCursor (0, IDC_ARROW); // optional
                _class.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1); // optional
                _class.lpszMenuName = 0;
                _class.lpszClassName = className; // mandatory
            }
            
            Once the Window Class is registered, we can proceed with the creation of a window. This is done by calling the CreateWindow API. It takes a lot of arguments: the name of the window class that we have just registered, the caption that will appear in the title bar, window style, position, size, and the application instance. The rest of the arguments, for the time being, will be left equal to zero.

            一旦窗口類注冊成功,我們就可以用它來創建一個窗口。我們通過調用CreateWindow這個API函數來完成它。它有很多參數,這可能讓你有點煩,不過不要進,你只要寫一次就好了。這些參數包括:我們剛剛注冊好的窗口類的名字(這個要是搞錯了,你的窗口可能就出不來了),我們窗口的標題欄上的標題,窗口的樣式,位置,大小還有應用程序的實例句柄。剩下的參數暫時我們還不需要用到,我們把它們初始化為0。

            This part of the program can also be encapsulated into a C++ class, WinMaker.

            程序的這部分也被我封裝到了一個C++的類WinMaker當中。

            The window will not appear on the screen until you tell Windows to show it.

            就算你創建好了窗口,但你還是看不到,你必須調用ShowWindow函數讓它顯示。
            class WinMaker
            {
            public:
                WinMaker (): _hwnd (0) {}
                WinMaker (char const * caption, 
                          char const * className,
                          HINSTANCE hInstance);
                void Show (int cmdShow)
                {
                    ::ShowWindow (_hwnd, cmdShow);
                    ::UpdateWindow (_hwnd);
                }
            protected:
                HWND _hwnd;
            };
            WinMaker::WinMaker (char const * caption, 
                                char const * className,
                                HINSTANCE hInstance)
            {
                _hwnd = ::CreateWindow (
                    className,            // name of a registered window class
                    caption,              // window caption
                    WS_OVERLAPPEDWINDOW,  // window style
                    CW_USEDEFAULT,        // x position
                    CW_USEDEFAULT,        // y position
                    CW_USEDEFAULT,        // witdh
                    CW_USEDEFAULT,        // height
                    0,                    // handle to parent window
                    0,                    // handle to menu
                    hInstance,            // application instance
                    0);                   // window creation data
            }
            
            A Windows program is event-driven. It means that you, as a programmer, are supposed to be on the defensive. The user will bombard Windows with various input actions, and Windows will bombard your program with messages corresponding to these actions. All you have to do is to respond to these messages. The picture below shows schematically how it works.

            Windows程序是事件驅動的。這就是說你作為一個windows程序員,所做的應該是防御式編程。其實也沒有這么嚴重。具體來說就是,用戶會發給windows多種輸入行為,而windows把這些輸入用消息的方式發給你的程序。而你,所做的就是針對每一個消息在回調函數中做出處理。下面的這張圖示意性的說明了這個過程。圖在下一頁的下一頁,o(∩_∩)o…

            Windows gets various events from the keyboard, the mouse, the ports, etc. Each event is quickly converted into a message. Windows (the operating system) dispatches messages to appropriate windows. For instance, all keyboard messages go to the window that currently has the input focus (the active window). Mouse messages are dispatched according to the position of the mouse cursor. They usually go to the window that is directly under the cursor (unless some program captured the mouse).

            首先,windows系統從鍵盤、鼠標、端口等等各種設備中獲得各種事件。每個事件被快速的轉換為消息。Windows分派這些消息給合適的窗口。舉個例子,所有的鍵盤消息都會傳給當前具有輸入焦點的窗口(也就是所謂的活動窗口)。鼠標消息則會根據鼠標光標所在的位置分派給相應的窗口。這些窗口通常是直接位于光標下的第一個窗口(除非有某些程序捕獲鼠標消息)。

            All these messages end up in message queues. Windows keeps a message queue for every running application (actually, for every thread). It is your duty to retrieve these messages one-by-one in what is called a message loop. Your program has to call GetMessage to retrieve a message. Then you call DispatchMessage to give it back to Windows. Couldn't Windows just go ahead and dispatch all these messages itself? In principle it could, but a message loop gives your program a chance to have a peek at them and maybe perform some additional actions before dispatching them. Or not...

            所有的消息都放在消息隊列里面。Windows為每一個運行的應用程序維護一個消息隊列(實際上,是為每一個線程)。把這些消息一個個的取出來,這是你的責任。通常我們把這段代碼叫做消息循環。在你的程序里,首先調用GetMessage函數取出一條消息,然后調用DispatchMessage把它返回給Windows。Windows還會重新分派這些消息嗎?原則上不會,但是你可以在消息循環中使用PeekMessage函數來查看消息而不分派它,因為某些情況下,你需要在分派這些消息之前做一些額外的工作。

            Each message is addressed to a particular window. When you tell Windows to dispatch such a message, it will figure out the class of this window, find the associated Window Procedure, and call it. Every single message sent to our window will end up in our window procedure. It is now up to us to respond to it. So, do we have to respond appropriately to every possible type of Windows message? There a hundreds of them! Fortunately, no! We only need to intercept those messages that we are interested in. Everything else we pass back to Windows for default processing using DefWindowProc.

            每個消息被傳遞到一個特殊的窗口。當你告訴windows分派一條信息的時候,windows會先找出這個窗口的類,然后找到與之關聯的窗口過程,最后調用這個窗口過程。每個發送到我們窗口的消息都會在我們的窗口過程中終止。現在輪到我們來處理這些消息了。因此,我們必須要處理所有的消息類型?不,這里有幾百種消息,我們只需要處理對我們有用的消息就可以了。但其它消息怎么辦呢?不用擔心,其它消息我們通過調用DefWindowProc這個函數來自動處理。

            Let's have a look at WinMain. The execution of a Windows program doesn't start in main--it starts in WinMain. In our WinMain, we create a WinClass and register it. Then we create an actual window (of the class we've just registered) and show it. Actually, WinMain is called with the appropriate show directive--the user might want to start the application minimized or maximized. So we just follow this directive. Next, we enter the message loop and keep retrieving and dispatching messages until GetMessage returns 0. At that point the message's wParam will contain the return code of the whole program.

            讓我們看看WinMain這個函數。一個windows函數的開始不是main函數,而是WinMain。在我們的winMain函數里,我們創建了一個WinClass的對象winClass,然后我們在windows中注冊了它。接下來我們創建了一個窗口(我們剛剛注冊的窗口類所對應的窗口)并且顯示它。實際上,WinMain由一個參數是用來指明窗口顯示效果的(這樣,用戶可以指定窗口顯示的方式)——用戶可能希望打開這個程序用最小化或者最大化的方式打開,因此,我們在這里只需要直接使用這個參數就可以了。然后我們進入消息循環并不斷取出消息和進行分派,直到GetMessage函數返回0。這個時候消息的wParam參數將會包含整個程序的返回值。
            int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInst,
                                char * cmdParam, int cmdShow)
            {
                char className [] = "Winnie";
                WinClass winClass (WindowProcedure, className, hInst);
                winClass.Register ();
                WinMaker win ("Hello Windows!", className, hInst);
                win.Show (cmdShow);
                
            MSG msg; int status; while ((status = ::GetMessage (& msg, 0, 0, 0)) != 0) { if (status == -1) return -1; ::DispatchMessage (& msg); }
            return msg.wParam; }
            The GetMessage API is an interesting example of the bizarre Microsoft Troolean (as opposed to traditional, Boolean) logic. GetMessage is defined to return a BOOL, but the documentation specifies three types of returns, non-zero, zero and -1. I am not making it up! Here's an excerpt from the help file:

            GetMessage函數是一個很好笑的微軟的三值布爾類型的例子。GetMessage函數定義的返回值是BOOL類型,但是文檔卻明確指出它含有三種返回值,非0、0和-1。我不想在這里多費口舌。下面是從MSDN中的摘錄。

            · If the function retrieves a message other than WM_QUIT, the return value is nonzero.
            · If the function retrieves the WM_QUIT message, the return value is zero.
            · If there is an error, the return value is -1.


            The other important part of every Windows program is the Windows Procedure. Remember, Windows will call it with all kinds of messages. All these messages can be ignored by sending them to DefWindowProc. There is only one message that we must intercept. That's the WM_DESTROY message that is sent by Windows when the user decides to close the window (by pressing the close button in the title bar). The standard response to WM_DESTROY is to post the quit message and return zero. That's all there is to it.

            讓我們看看所有windows程序都很重要的回調函數吧。你需要注意的是,windows將為所有的消息調用這個函數。所以剩余的消息一定要送給DefWindowProc去處理。在這里我們只處理了一個消息。那就是WM_DESTROY。當用戶要關閉一個窗口的時候,windows會發送這個消息。標準的處理WM_DESTROY消息是發送一條退出消息,并返回0。好了,這就是我們要講的全部了。*_*

            // Window Procedure called by Windows
            LRESULT CALLBACK WindowProcedure
                (HWND hwnd, unsigned int message, WPARAM wParam, LPARAM lParam)
            {
                switch (message)
                {
                    case WM_DESTROY:
                        ::PostQuitMessage (0);
                        return 0;
                }
                return ::DefWindowProc (hwnd, message, wParam, lParam );
            }
            
            posted on 2008-09-23 11:01 聶元朗 閱讀(2253) 評論(4)  編輯 收藏 引用 所屬分類: windows程序學習筆記

            Feedback

            # re: 翻譯-C++最簡單的windows程序 The Simplest Windows Program 2008-09-23 17:45 adcx
            練習英文翻譯?否則這種文章翻譯沒什么價值的  回復  更多評論
              

            # re: 翻譯-C++最簡單的windows程序 The Simplest Windows Program 2008-09-23 21:45 聶元朗
            @adcx
            你懂了所以不需要了,但我沒懂所以需要!明白?  回復  更多評論
              

            # re: 翻譯-C++最簡單的windows程序 The Simplest Windows Program 2008-09-25 14:48 Barrys
            @adcx
            貴在積累嘛  回復  更多評論
              

            # re: 翻譯-C++最簡單的windows程序 The Simplest Windows Program 2008-09-25 15:30 肥仔
            翻譯這個,有意思嗎?  回復  更多評論
              

            久久综合狠狠综合久久| 99久久精品国产毛片| 日韩欧美亚洲综合久久影院d3| 久久精品a亚洲国产v高清不卡| 久久精品国产亚洲AV麻豆网站| AV无码久久久久不卡蜜桃| 91精品日韩人妻无码久久不卡| 久久久精品国产Sm最大网站| 亚洲国产成人久久一区久久| 一本色道久久88精品综合| 国产精品对白刺激久久久| 久久久国产精华液| 狠狠色丁香婷婷综合久久来| 四虎久久影院| 观看 国产综合久久久久鬼色 欧美 亚洲 一区二区 | 人妻系列无码专区久久五月天| 伊人久久国产免费观看视频 | 成人a毛片久久免费播放| 99久久做夜夜爱天天做精品| 婷婷五月深深久久精品| 国产免费久久精品99久久| 久久天天躁夜夜躁狠狠躁2022| 久久www免费人成精品香蕉| 国内精品伊人久久久久777| 久久久青草青青亚洲国产免观| 国产美女亚洲精品久久久综合| 色综合久久中文色婷婷| 久久男人Av资源网站无码软件| 久久人人超碰精品CAOPOREN| 国产精品福利一区二区久久| 亚洲va久久久噜噜噜久久| 午夜精品久久影院蜜桃| 久久国产乱子伦精品免费强| 久久综合久久性久99毛片| 久久成人国产精品一区二区| 久久精品成人免费网站| 无码人妻久久一区二区三区免费丨| 久久久亚洲精品蜜桃臀| 国内精品免费久久影院| 丁香五月网久久综合| 一本一道久久综合狠狠老|