• <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++博客 :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
              16 Posts :: 0 Stories :: 6 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(1)

            我參與的團(tuán)隊

            搜索

            •  

            最新隨筆

            最新評論

            閱讀排行榜

            評論排行榜

            來自: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.

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

            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應(yīng)用程序而不是windows控制臺程序。否則,你就會得到找不到main函數(shù)的錯誤。在VC++6.0中,我們可以通過選擇File——New Projects——Win32 Application來創(chuàng)建一個windows應(yīng)用程序的工程。當(dāng)然,你用不著這么擔(dān)心,我已經(jīng)提供了兩個做好的工程文件給你。一個是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++中的類,這個窗口類相當(dāng)于C語言中的結(jié)構(gòu)體,你把這個結(jié)構(gòu)體填好了,然后你的應(yīng)用程序就會根據(jù)你填的這些信息來顯示窗口。在我們的例子里面,我們僅僅顯示一個窗口。但是就算是這樣,我們也必須要給我們的窗口最少的窗口類信息。而其中最重要的部分就是回調(diào)函數(shù)了,有時候我們也稱它為窗口過程。其實這是一個函數(shù)指針,每次程序需要處理消息的時候,windows就通過這個函數(shù)指針來調(diào)用我們寫好的回調(diào)函數(shù)。是的,你看到,是windows調(diào)用我們編寫的函數(shù)。你還記得函數(shù)指針嗎?如果不是很清楚,可以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(窗口過程、回調(diào)函數(shù))的定義。仔細(xì)看一下,第一個函數(shù)是一個句柄,也就是個整數(shù)。Windows用它來區(qū)別是哪個窗口。然后是消息,然后是與消息關(guān)系密切的兩個參數(shù)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,鼠標(biāo)光標(biāo)(我們僅僅加載了標(biāo)準(zhǔn)的箭頭鼠標(biāo)),畫窗口背景的畫刷(我們用的是窗口缺省的背景顏色畫刷),最后還有窗口類的名字(窗口類的名字最好和別人的不同).(當(dāng)然,現(xiàn)在你不需要弄明白這些參數(shù)的意義)

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

            一旦我們把WNDCLASS結(jié)構(gòu)體填完了,我們就通過調(diào)用RegisterClass函數(shù)在windows系統(tǒng)中注冊我們的窗口類。好了,先看看我是怎樣封裝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.

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

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

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

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

            就算你創(chuàng)建好了窗口,但你還是看不到,你必須調(diào)用ShowWindow函數(shù)讓它顯示。
            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程序是事件驅(qū)動的。這就是說你作為一個windows程序員,所做的應(yīng)該是防御式編程。其實也沒有這么嚴(yán)重。具體來說就是,用戶會發(fā)給windows多種輸入行為,而windows把這些輸入用消息的方式發(fā)給你的程序。而你,所做的就是針對每一個消息在回調(diào)函數(shù)中做出處理。下面的這張圖示意性的說明了這個過程。圖在下一頁的下一頁,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系統(tǒng)從鍵盤、鼠標(biāo)、端口等等各種設(shè)備中獲得各種事件。每個事件被快速的轉(zhuǎn)換為消息。Windows分派這些消息給合適的窗口。舉個例子,所有的鍵盤消息都會傳給當(dāng)前具有輸入焦點的窗口(也就是所謂的活動窗口)。鼠標(biāo)消息則會根據(jù)鼠標(biāo)光標(biāo)所在的位置分派給相應(yīng)的窗口。這些窗口通常是直接位于光標(biāo)下的第一個窗口(除非有某些程序捕獲鼠標(biāo)消息)。

            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為每一個運行的應(yīng)用程序維護(hù)一個消息隊列(實際上,是為每一個線程)。把這些消息一個個的取出來,這是你的責(zé)任。通常我們把這段代碼叫做消息循環(huán)。在你的程序里,首先調(diào)用GetMessage函數(shù)取出一條消息,然后調(diào)用DispatchMessage把它返回給Windows。Windows還會重新分派這些消息嗎?原則上不會,但是你可以在消息循環(huán)中使用PeekMessage函數(shù)來查看消息而不分派它,因為某些情況下,你需要在分派這些消息之前做一些額外的工作。

            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.

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

            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這個函數(shù)。一個windows函數(shù)的開始不是main函數(shù),而是WinMain。在我們的winMain函數(shù)里,我們創(chuàng)建了一個WinClass的對象winClass,然后我們在windows中注冊了它。接下來我們創(chuàng)建了一個窗口(我們剛剛注冊的窗口類所對應(yīng)的窗口)并且顯示它。實際上,WinMain由一個參數(shù)是用來指明窗口顯示效果的(這樣,用戶可以指定窗口顯示的方式)——用戶可能希望打開這個程序用最小化或者最大化的方式打開,因此,我們在這里只需要直接使用這個參數(shù)就可以了。然后我們進(jìn)入消息循環(huán)并不斷取出消息和進(jìn)行分派,直到GetMessage函數(shù)返回0。這個時候消息的wParam參數(shù)將會包含整個程序的返回值。
            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函數(shù)是一個很好笑的微軟的三值布爾類型的例子。GetMessage函數(shù)定義的返回值是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程序都很重要的回調(diào)函數(shù)吧。你需要注意的是,windows將為所有的消息調(diào)用這個函數(shù)。所以剩余的消息一定要送給DefWindowProc去處理。在這里我們只處理了一個消息。那就是WM_DESTROY。當(dāng)用戶要關(guān)閉一個窗口的時候,windows會發(fā)送這個消息。標(biāo)準(zhǔn)的處理WM_DESTROY消息是發(fā)送一條退出消息,并返回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程序?qū)W習(xí)筆記

            Feedback

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

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

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

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

            国产香蕉97碰碰久久人人| 久久精品国产亚洲AV影院| 少妇高潮惨叫久久久久久| 亚洲乱码中文字幕久久孕妇黑人| 97精品国产97久久久久久免费| 久久国产色AV免费看| 久久精品一本到99热免费| 欧美午夜A∨大片久久 | 欧美激情精品久久久久久久九九九| 久久久久国产精品三级网 | 久久精品a亚洲国产v高清不卡| 久久久青草青青亚洲国产免观| 久久免费99精品国产自在现线| 国内精品伊人久久久久777| 精品999久久久久久中文字幕| 久久强奷乱码老熟女| 久久水蜜桃亚洲av无码精品麻豆| 国内精品久久久久久麻豆| 99久久国产综合精品女同图片| 国产—久久香蕉国产线看观看| 久久ZYZ资源站无码中文动漫| 91麻豆国产精品91久久久| 久久精品国产精品亚洲精品| 亚洲国产精品无码久久一线| 国内精品久久久久影院薰衣草| 久久久这里有精品中文字幕| 无码超乳爆乳中文字幕久久| 久久中文字幕精品| 国产精品免费久久久久久久久| 国产精品视频久久| 伊人久久大香线蕉综合影院首页| 久久免费视频1| 久久久久国产精品三级网| 久久久久九九精品影院| 久久精品中文字幕久久| 国产精品久久久久无码av | 亚洲伊人久久综合影院| 国产精品免费久久久久久久久| 久久精品国产72国产精福利| 国产国产成人久久精品| 国产成人精品久久一区二区三区av |