青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

朗朗空間

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

  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 聶元朗 閱讀(2284) 評論(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 肥仔
翻譯這個,有意思嗎?  回復  更多評論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美一区二区高清| 国产亚洲免费的视频看| 一区二区精品| 亚洲大片在线| 亚洲国产高清自拍| 亚洲精品国产精品国产自| 狠狠干综合网| 亚洲国产精品黑人久久久| 亚洲电影有码| 亚洲六月丁香色婷婷综合久久| 亚洲精品一二| 亚洲网站在线播放| 欧美在线视频播放| 久久全球大尺度高清视频| 麻豆精品视频在线观看| 欧美刺激性大交免费视频| 亚洲国产日韩欧美| 亚洲国产精品福利| 99精品国产一区二区青青牛奶| 一区二区三区产品免费精品久久75 | 狠狠色香婷婷久久亚洲精品| 黄色小说综合网站| 亚洲天堂av综合网| 六月婷婷久久| 一区二区三区免费观看| 久久久久久久久久久一区| 欧美日韩一二三四五区| 国产亚洲免费的视频看| 亚洲一二区在线| 蜜臀va亚洲va欧美va天堂| 99视频国产精品免费观看| 久久丁香综合五月国产三级网站| 牛夜精品久久久久久久99黑人| 欧美日韩在线三级| 91久久精品国产91久久性色tv| 香蕉久久国产| 99精品久久久| 欧美精品免费在线观看| 一区二区亚洲欧洲国产日韩| 亚洲欧美日韩区| 亚洲日本在线观看| 老鸭窝91久久精品色噜噜导演| 国产精品网曝门| 国产精品99久久不卡二区| 欧美高清免费| 久久婷婷综合激情| 一区二区三区我不卡| 欧美中文在线观看国产| 一区二区三区四区五区视频| 欧美高清视频一二三区| 亚洲韩国青草视频| 欧美成人精品一区| 中国亚洲黄色| 欧美成人一品| 在线日韩av永久免费观看| 在线观看日韩专区| 亚洲与欧洲av电影| 亚洲欧洲在线看| 亚洲人成绝费网站色www| 久久婷婷久久一区二区三区| 欧美成人精品一区二区| 免费av成人在线| 亚洲日本中文| 亚洲黄色一区| 日韩小视频在线观看专区| 激情久久一区| 久久伊伊香蕉| 欧美高清在线| 国产精品有限公司| 亚洲精品欧美一区二区三区| 久久精品亚洲一区二区三区浴池| 99riav久久精品riav| 欧美福利视频在线| 亚洲精品免费在线播放| 亚洲国产精品成人| 欧美国产国产综合| 亚洲精品中文字幕在线观看| 欧美国产第一页| 欧美国产免费| 一区二区三区国产精品| 一区二区三区成人 | 久久在精品线影院精品国产| 韩国成人福利片在线播放| 亚洲少妇诱惑| 国产精品免费小视频| 久久久www成人免费毛片麻豆| 久久人人爽人人爽爽久久| 亚洲精品九九| 欧美寡妇偷汉性猛交| 欧美高清视频在线| 99日韩精品| 午夜精品国产| 亚洲欧美日韩精品综合在线观看| 亚洲国产午夜| 欧美va亚洲va国产综合| 亚洲国产成人久久| 国产亚洲精品bv在线观看| 亚洲综合视频网| 久久久精品国产免费观看同学| 激情欧美国产欧美| 久久av二区| 午夜在线精品偷拍| 欧美亚日韩国产aⅴ精品中极品| 国产日韩精品综合网站| 欧美一区二区三区四区视频| 久久精品日产第一区二区| 91久久精品美女| 亚洲制服丝袜在线| 亚洲精品一区二| 久久www成人_看片免费不卡| 日韩一二三在线视频播| 欧美一二三区在线观看| 夜夜精品视频一区二区| 久久久久国产一区二区三区四区| 99成人免费视频| 久久精品五月| 亚洲欧美日韩综合aⅴ视频| 久久久97精品| 午夜久久美女| 欧美午夜精品一区二区三区| 欧美成人午夜激情视频| 国产女精品视频网站免费| 亚洲国产一二三| 狠狠色综合网| 欧美一区2区三区4区公司二百| 国产精品vvv| 亚洲区在线播放| 亚洲国产另类久久精品| 久久激情五月婷婷| 亚洲欧美精品中文字幕在线| 欧美精品亚洲精品| 欧美黄色影院| 亚洲成人中文| 久久久女女女女999久久| 欧美在线视频一区二区| 国产精品久久久久久户外露出| 欧美刺激午夜性久久久久久久| 在线观看视频欧美| 欧美一区二区视频观看视频| 先锋影音网一区二区| 欧美视频你懂的| 亚洲毛片在线观看| 亚洲精品男同| 欧美女人交a| 亚洲精品乱码久久久久久久久| 最新中文字幕亚洲| 欧美—级高清免费播放| 欧美韩国日本一区| 亚洲国产黄色| 欧美精品久久久久久| 久久一区欧美| 亚洲九九精品| 欧美日韩亚洲天堂| 亚洲精品乱码久久久久久日本蜜臀| 亚洲国产精品久久久久婷婷884| 久久嫩草精品久久久精品| 久久免费高清| 亚洲国产mv| 国产亚洲电影| 久久久久久久久久久久久久一区| 亚洲一区在线播放| 国产精品欧美日韩一区| 亚洲美女网站| 一本色道久久综合亚洲91| 亚洲春色另类小说| 一区二区三区视频在线| 夜夜精品视频| 午夜久久tv| 欧美午夜精品一区| 国精产品99永久一区一区| 久久一区激情| 亚洲最新在线视频| 午夜一区二区三视频在线观看| 老鸭窝91久久精品色噜噜导演| 国产日本亚洲高清| 亚洲免费观看在线观看| 午夜精品视频在线| 99在线精品观看| 亚洲美女视频在线观看| 欧美日韩国产色视频| 激情综合在线| 亚洲精品日韩在线观看| 在线观看不卡| 久久亚洲国产精品一区二区 | 夜夜爽www精品| ●精品国产综合乱码久久久久| 亚洲国产精彩中文乱码av在线播放| 亚洲一区在线观看免费观看电影高清 | 亚洲日本黄色| 亚洲国产影院| 亚洲国产综合在线| 最近看过的日韩成人| 亚洲第一毛片| 麻豆久久精品| 免费亚洲一区| 精品成人a区在线观看| 久久国产精品一区二区| 久久国产精品网站| 欧美激情国产精品| 亚洲视频免费在线|