⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winnie.html

📁 很好的,电子书籍,我找了好久的
💻 HTML
字号:
<html>
<head>
<title>Hello Windows!</title>
<meta  name="description" content="Reliable software Win32 Tutorial: Simplest program">
<meta name="keywords" content="reliable, software, windows, cplusplus, source code, example, tutorial, object oriented, message loop, CreateWindow, WinMain, window procedure, RegisterClass">
</head>

<body background="../images/grid.gif" bgcolor="white" text="black">

<table cellpadding=10 width="100%">
<tr>
   <td width=100 align=center valign=middle>
      <a href="../index.htm">
      <img src="../images/rsbullet.gif" alt="RS" border=0 width=39 height=39>
      <br>Home</a>
   <td><font face="arial" color="#009966">
       <h1 align=center>The Simplest Windows Program</h1>
       </font>
</table>


<p>
<table width="100%">
<tr>
   <td width=80> <!-- Left margin -->
   <td> <!-- Middle column, there is also the right margin at the end -->

   <table cellpadding=10 cellspacing=0 width="100%">
   <tr>
   <td bgcolor="#ffffff">


<hr>
<font size="+1"><b>Before you can even</b></font> begin thinking about programming in Windows, you have to be able to understand how this simple program works. Remember to compile this and other Windows programs with the <b>STRICT</b> compilation flag defined!

<p>Note: This is a Win32 program-- it will run under Windows 95 and Windows NT (if they want you to program for the 16-bit platform, they should pay you twice as much!). Windows API calls  are highlighted in <font color="#000099"><b>blue</b></font> and Windows specific data types are shown in <font color="#009966">green</font>. 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.
<p><a href="source/winnie.zip">Sources</a> (zipped file 3k) are right here. Remember to compile them as a <i>Windows</i> application. For instance, in Visual C++ select <b>File.New.Projects.Win32 Application</b>. Otherwise you'll get the error: unresolved external <i>_main</i>. (I provided a project file for those of you who use MS VC++ 6.0)
<hr>
First, you have to define a class of windows that will be displayed by your application. 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 <b>WinClass</b> is the address of the callback procedure, or the Window Procedure. Windows is supposed to call <i>us</i>--it sends messages to our program by calling this procedure.
<p>Notice the declaration of <b>WindowProcedure</b>. Windows will call us with a handle to the window in question, the message, and two data items associated with the message, the paramters, <font color="#009966">WPARAM</font> and <font color="#009966">LPARAM</font>.
<p>In WinClass we also have to specify things like the program instance handle <font color="#009966">HINSTANCE</font>, 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 name of our class.
<p>Once all the fields of <font color="#009966">WNDCLASS</font> are filled, we register the class with the Windows system.
<hr>
<pre><font face="courier">#include &lt;windows.h&gt;


LRESULT CALLBACK <font color="#cc0066"><b>WindowProcedure</b></font>
    (<font color="#009966">HWND</font> hwnd, unsigned int message, <font color="#009966">WPARAM</font> wParam, <font color="#009966">LPARAM</font> lParam);

class <font color="#cc0066"><b>WinClass</b></font>
{
public:
    WinClass (WNDPROC winProc, char const * className, HINSTANCE hInst);
    void Register ()
    {
        <font color="#000099"><b>::RegisterClass</b></font> (&amp;_class);
    }
private
    <font color="#009966">WNDCLASS</font> _class;
};

<font color="#cc0066"><b>WinClass::WinClass</b></font>
    (<font color="#009966">WNDPROC</font> winProc, char const * className, <font color="#009966">HINSTANCE</font> hInst)
{
    _class.style = 0;
    <b>_class.lpfnWndProc = winProc;</b> // window procedure: mandatory
    _class.cbClsExtra = 0;
    _class.cbWndExtra = 0;
    _class.hInstance = hInst;         // owner of the class: mandatory
    _class.hIcon = 0;
    _class.hCursor = ::<font color="#000099"><b>LoadCursor</b></font> (0, IDC_ARROW); // optional
    _class.hbrBackground = (<font color="#009966">HBRUSH</font>) (COLOR_WINDOW + 1); // optional
    _class.lpszMenuName = 0;
    _class.lpszClassName = className; // mandatory
}
</font></pre>
<hr><!--Text-->
Once the Window Class is registered, we can proceed with the creation of a window. This is done by calling the <font color="#000099"><b>CreateWindow</b></font> 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, style, position and size, and the application instance. The rest of the arguments, for the time being, will be left equal to zero.
<p>The window will not appear on the screen until you tell Windows to show it.
<hr>
<pre><font face="courier">
class <font color="#cc0066"><b>WinMaker</b></font>
{
public:
    WinMaker (): _hwnd (0) {}
    WinMaker (char const * caption, char const * className, <font color="#009966">HINSTANCE</font> hInstance);
    void Show (int cmdShow)
    {
        <font color="#000099"><b>::ShowWindow</b></font> (_hwnd, cmdShow);
        <font color="#000099"><b>::UpdateWindow</b></font> (_hwnd);
    }
protected:
    <font color="#009966">HWND</font> _hwnd;
};

<font color="#cc0066"><b>WinMaker::WinMaker</b></font>
    (char const * caption, char const * className, <font color="#009966">HINSTANCE</font> hInstance)
{
    _hwnd = ::<font color="#000099"><b>CreateWindow</b></font> (
        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
}
</font></pre>
<hr><!--Text-->
A Windows program is <b>event-driven</b>. 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.
<p>Windows gets various events from the keyboard, the mouse, the ports, etc. Each event is quickly converted into a message. Windows dispatches messages to appropriate windows. For instance, all  keyboard messages go to the window that currently has the <b>input focus</b> (the <i>active</i> 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).
<p>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 <font color="#000099"><b>GetMessage</b></font> to retrieve a message. Then you call <font color="#000099"><b>DispatchMessage</b></font> 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...
<p>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 react 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 these messages that we are interested in. Everything else we pass back to Windows for default processing using <font color="#000099"><b>DefWindowProc</b></font>.
<hr>
<img src="images/windisp.gif" alt="Windows dispatch mechanism" width=474 height=258>
<hr>
Let's have a look at <font color="#cc0066"><b>WinMain</b></font>. The execution of a Windows program doesn't start in <font color="#cc0066"><b>main</b></font>--it starts in <font color="#cc0066"><b>WinMain</b></font>. First, we create a WinClass and register it. Then we create an actual window (of the class we've just registered) and show it. Actually, <font color="#cc0066"><b>WinMain</b></font> is called with the appropriate <i>show</i> 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 <font color="#000099"><b>GetMessage</b></font> returns 0. At that point the message's wParam will contain the return code of the whole program.

<hr><!--End Text-->

<font face="courier"><pre>int WINAPI <font color="#cc0066"><b>WinMain</b></font> (<font color="#009966">HINSTANCE</font> hInst, <font color="#009966">HINSTANCE</font> hPrevInst,
            char * cmdParam, int cmdShow)
{
    char className [] = "Winnie";

    WinClass winClass (WindowProcedure, className, hInst);
    winClass.Register ();

    WinMaker win ("Hello Windows!", className, hInst);
    win.Show (cmdShow);

    <font color="#009966">MSG</font>  msg;
    int status;

    while ((status = ::<font color="#000099"><b>GetMessage</b></font> (&amp; msg, 0, 0, 0)) != 0)
    {
        if (status == -1)
            return -1;
        ::<font color="#000099"><b>DispatchMessage</b></font> (&amp; msg);
    }

    return msg.wParam;
}</pre></font>
<table cellpadding=5><tr>
<td width=10>&nbsp</td>
<td bgcolor="#cccccc">
The <font color="#000099"><b>GetMessage</b></font> API is an interesting example of the bizarre Microsoft <i>Troolean</i> (as opposed to traditional, <i>Boolean</i>) logic. <font color="#000099"><b>GetMessage</b></font> is defined to return a <font color="#009966">BOOL</font>, 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:
<ul>
<li>If the function retrieves a message other than <font color="#009966">WM_QUIT</font>, the return value is <b>nonzero</b>. 
<li>If the function retrieves the <font color="#009966">WM_QUIT</font> message, the return value is <b>zero</b>. 
<li>If there is an error, the return value is <b>-1</b>. 
</ul>


</td></tr>
</table>
<hr>
The other part of a 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 <font color="#000099"><b>DefWindowProc</b></font>. There is only one message that we <i>must</i> intercept. That's the <font color="#009966">WM_DESTROY</font> message that is sent by Windows when the user decides to close the window (by pressing the <i>close</i> button in the title bar). The standard response to <font color="#009966">WM_DESTROY</font> is to post the quit message and return zero. That's all there is to it.
<hr><!--Text-->

<pre><font face="courier">
// Window Procedure called by Windows

LRESULT CALLBACK <font color="#cc0066"><b>WindowProcedure</b></font>
    (<font color="#009966">HWND</font> hwnd, unsigned int message, <font color="#009966">WPARAM</font> wParam, <font color="#009966">LPARAM</font> lParam)
{
    switch (message)
    {
        case WM_DESTROY:
            ::<font color="#000099"><b>PostQuitMessage</b></font> (0);
            return 0;

    }
    return ::<font color="#000099"><b>DefWindowProc</b></font> (hwnd, message, wParam, lParam );
}

</font></pre>
<hr>
This is actually the ugliest, least object oriented part of encapsulating Windows. It's getting better from this point on. Like in this <a href="generic.html">generic</a> Windows program.
<hr>
   </table>
   <td width=60>
</table>


</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -