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

朗朗空間

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

  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 聶元朗 閱讀(2283) 評論(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>
            亚洲午夜精品久久久久久浪潮| 欧美一区二区播放| 激情久久综艺| 亚洲狼人精品一区二区三区| 国产视频一区在线观看一区免费 | 136国产福利精品导航网址| 一区二区三区三区在线| 久久亚洲图片| 亚洲午夜伦理| 国产精品推荐精品| 亚洲人成人一区二区三区| 久久这里有精品视频| 亚洲一级影院| 欧美日本免费一区二区三区| 亚洲国产精品一区制服丝袜| 久久狠狠久久综合桃花| 欧美一级大片在线观看| 国产精品久久久久婷婷| 亚洲欧美成aⅴ人在线观看| 亚洲精品一区在线观看香蕉| 久久亚洲综合网| 亚洲精品久久视频| 欧美电影在线观看完整版| 女主播福利一区| 亚洲黄色高清| 性欧美xxxx视频在线观看| 午夜一级久久| 日韩午夜在线电影| 国产精品久久久久久模特| 99精品视频免费全部在线| 日韩一二三区视频| 欧美日韩免费观看一区三区 | 国产日韩精品一区二区浪潮av| 99热在这里有精品免费| 一区二区三区视频在线播放| 久久一区二区三区超碰国产精品| 最新国产精品拍自在线播放| 免费视频一区| 麻豆精品一区二区av白丝在线| 亚洲欧洲在线一区| 91久久综合亚洲鲁鲁五月天| 亚洲欧美日韩综合aⅴ视频| 国产精品免费观看视频| 欧美一级片一区| 老司机凹凸av亚洲导航| 永久555www成人免费| 美女尤物久久精品| 欧美日韩免费观看一区| 亚洲一区二区三区四区五区午夜| 亚洲三级国产| 国产精品揄拍500视频| 欧美在线观看视频一区二区| 欧美18av| 午夜精品一区二区三区电影天堂| 久久久久99精品国产片| 亚洲高清影视| 91久久国产综合久久| 国产欧美日本一区视频| 久久精品视频在线看| 欧美黄色日本| 久久超碰97中文字幕| 久久亚洲一区二区| 午夜精品视频| 免费永久网站黄欧美| 久久精品99久久香蕉国产色戒| 久久人人97超碰国产公开结果| 尤物视频一区二区| 在线亚洲免费| 玉米视频成人免费看| 亚洲一区二区精品在线观看| 在线成人黄色| 欧美一区国产二区| 99综合精品| 欧美成人高清视频| 久久精品91久久久久久再现| 欧美国产成人精品| 欧美激情第3页| 国产日韩欧美黄色| 亚洲一区二区成人在线观看| 在线成人h网| 久久精品视频免费观看| 亚洲综合精品| 麻豆精品一区二区综合av| 欧美一区二区三区另类| 欧美激情第五页| 亚洲国产精品电影| 国产欧美日韩不卡| 亚洲男人的天堂在线aⅴ视频| 136国产福利精品导航网址| 久久精品1区| 欧美日韩高清一区| 日韩一区二区免费高清| 亚洲电影免费观看高清完整版在线观看 | 欧美日韩天天操| 亚洲国产成人在线| 韩国在线视频一区| 一区二区三区视频在线| 亚洲午夜在线| 欧美成人一区二区在线| 亚洲第一中文字幕| 韩国av一区二区三区在线观看 | 欧美激情性爽国产精品17p| 黄色亚洲在线| 性色av一区二区怡红| 久久国产欧美精品| 国产精品美女黄网| 欧美一区国产在线| 久久精品导航| 亚洲福利视频一区二区| 久久精品视频在线| 久久久久成人精品| 亚洲激情视频在线| 看欧美日韩国产| 亚洲人成人一区二区三区| 亚洲黄色一区| 亚洲综合成人在线| 久久精品综合一区| 国产精品久久久久aaaa樱花| 中日韩午夜理伦电影免费| a4yy欧美一区二区三区| 国产精品日韩二区| 亚洲永久精品国产| 免费久久99精品国产| 亚洲黄色视屏| 久久色在线播放| 亚洲精品色婷婷福利天堂| 黄色一区二区在线| 欧美午夜a级限制福利片| 亚洲校园激情| 亚洲高清中文字幕| 中文精品在线| 国产一区二区精品在线观看| 久久精品中文字幕免费mv| 亚洲人成绝费网站色www| 亚洲一线二线三线久久久| 欧美成人精品一区二区| 亚洲字幕在线观看| 久久综合色婷婷| 亚洲欧美日韩精品综合在线观看| 国产精品日韩一区二区| 欧美高清在线观看| 亚洲一区二区少妇| 性色av香蕉一区二区| 亚洲大胆人体视频| 欧美日韩另类在线| 玖玖精品视频| 日韩亚洲在线| 亚洲大片精品永久免费| 欧美香蕉大胸在线视频观看| 久久精品成人一区二区三区| 欧美岛国激情| 久久久成人网| 一区二区三区日韩在线观看| 狠狠爱www人成狠狠爱综合网| 欧美另类videos死尸| 亚洲人成人一区二区在线观看| 久久久久久9999| 日韩视频精品| 亚洲欧洲精品一区| 国产精品国产三级欧美二区| 欧美第十八页| 欧美一区二区视频97| 亚洲视频在线观看三级| 免费看亚洲片| 99亚洲伊人久久精品影院红桃| 亚洲国产91| 国产日产欧美a一级在线| 欧美午夜电影完整版| 久久人人爽国产| 久久午夜精品| 亚洲欧美视频在线观看| 亚洲欧美bt| 正在播放欧美一区| 亚洲精品在线视频| 亚洲第一区在线观看| 久久五月天婷婷| 欧美中文字幕不卡| 亚洲国产91精品在线观看| 欧美日韩一区二区在线视频| 中文在线一区| 一区二区国产在线观看| 亚洲三级免费| 亚洲作爱视频| 亚洲欧洲三级| 一区二区三区.www| 亚洲精品一区在线| 一区二区高清视频| 夜夜嗨av一区二区三区网页 | 欧美日韩中文在线| 久久久亚洲影院你懂的| 免费观看不卡av| 久久影音先锋| 欧美日韩福利在线观看| 欧美成年网站| 国产精品久久午夜| 国产精品国产三级国产普通话99| 国产精品在线看| 国产一区视频在线观看免费| 伊大人香蕉综合8在线视| 一区在线观看|