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

📄 1hello.html

📁 Visual C++ has been one of most effective tool for the large industrial applications. This book is t
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<pre>class WinMaker
{
public:
    WinMaker (char const * className, HINSTANCE hInst);
    HWND Create (char const * title);
private:
    HINSTANCE    _hInst;        // program instance
    char const  *_className;     // name of Window class
    DWORD        _style;        // window style
    DWORD        _exStyle;      // window extended style
    int          _x;             // horizontal position of window
    int          _y;             // vertical position of window
    int          _width;         // window width  
    int          _height;        // window height
    HWND         _hWndParent;    // handle to parent or owner window
    HMENU        _hMenu;         // handle to menu, or child-window id
    void *       _data;          // pointer to window-creation data
};</pre>
</td></tr></table><!-- End Code -->


<p>The constructor of <var>WinMaker</var> takes the title of the window and the name of its Window class. The title will be displayed in the title bar, the class name is necessary for Windows to find the window procedure for this window. The rest of the parameters are given some reasonable default values. For instance, we let the system decide the initial position and size of our window. The style, <var>WS_OVERLAPPEDWINDOW</var>, is the most common style for top-level windows. It includes a title bar with a system menu on the left and the minimize, maximize and close buttons on the right. It also provides for a "thick" border that can be dragged with the mouse in order to resize the window.

<!-- Code --><table width=100% cellspacing=10><tr>    <td class=codetable>
<pre>WinMaker::WinMaker (char const * className, HINSTANCE hInst)
  : _style (WS_OVERLAPPEDWINDOW),
    _exStyle (0),
    _className (className),
    _x (CW_USEDEFAULT), // horizontal position of window
    _y (0),             // vertical position of window
    _width (CW_USEDEFAULT), // window width  
    _height (0),        // window height
    _hWndParent (0),    // handle to parent or owner window
    _hMenu (0),         // handle to menu, or child-window identifier
    _data (0),          // pointer to window-creation data
    _hInst (hInst)
{}</pre>
</td></tr></table><!-- End Code -->

<p>All these paramters are passed to the <var>::CreateWindowEx</var> API that creates the window (but doesn't display it yet).
<!-- Code --><table width=100% cellspacing=10><tr>    <td class=codetable>
<pre>HWND WinMaker::Create (char const * title)
{
    HWND hwnd = ::CreateWindowEx (
        _exStyle,
        _className,
        title,
        _style,
        _x,
        _y,
        _width,
        _height,
        _hWndParent,
        _hMenu,
        _hInst,
        _data);
 
    if (hwnd == 0)
        throw "Window Creation Failed";
    return hwnd;
}</pre>
</td></tr></table><!-- End Code -->

<p><var>Create</var> returns a handle to the successfully created window. We will conveniently encapsulate this handle in a class called <var>Window</var>. Other than storing a handle to a particular window, this class will provide interface to a multitude of Windows APIs that operate on that window. 
<!-- Code --><table width=100% cellspacing=10><tr>    <td class=codetable>
<pre>class Window
{
public:
    Window (HWND h = 0) : _h (h) {}
    void Display (int cmdShow)
    {
        assert (_h != 0);
        ::ShowWindow (_h, cmdShow); 
        ::UpdateWindow (_h); 
    }
private:
    HWND _h;
};</pre>
</td></tr></table><!-- End Code -->

<p>To make the window visible, we have to call <var>::ShowWindow</var> with the appropriate parameter, which specifies whether the window should be initially minimized, maximized or regular-size. <var>::UpdateWindow</var> causes the contents of the window to be refreshed.

<p>The window procedure must have the following signature, which is hard-coded into Windows:

<!-- Code --><table width=100% cellspacing=10><tr>    <td class=codetable>
<pre>LRESULT CALLBACK WinProcedure
    (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);</pre>
</td></tr></table><!-- End Code -->

<p>Notice the calling convention and the types of parameters and the return value. These are all typedefs defined in windows.h. <var>CALLBACK</var> is a predefined language-independent calling convention (what order the parameters are pushed on the stack, etc.). <var>LRESULT</var> is a type of return value. <var>HWND</var> is a handle to a window, <var>UINT</var> is an unsigned integer that identifies the message, <var>WPARAM</var> and <var>LPARAM</var> are the types of the two parameters that are passed with every message. 
<p><var>WinProcedure</var> is called by Windows every time it wants to pass a message to our program. The window handle identifies the window that is supposed to respond to this message. Remember that he same Window procedure may service several instances of the same Windows class. Each instance will have its own window with a different handle, but they will all go through the same procedure.

<p align="CENTER"><img src="Image2-1.gif" tppabs="http://www.relisoft.com/book/win/images/Image2.gif" width=354 height=192>
<p>Figure. The relationship between instances of the same program, their windows and the program抯 Window class and procedure.

<p>The message is just a number. Symbolic names for these numbers are defined in windows.h. For instance, the message that tells the window to repaint itself is defined as
<!-- Code --><table width=100% cellspacing=10><tr>    <td class=codetable>
<pre>#define WM_PAINT        0x000F</pre>
</td></tr></table><!-- End Code -->


<p>Every message is accompanied by two parameters whose meaning depends on the kind of message. (In the case of <var>WM_PAINT</var> the parameters are meaningless.)
<p>To learn more about window procedure study the help files that come with your compiler. 
<p>Here抯 our minimalist implementation of Window procedure.
<!-- Code --><table width=100% cellspacing=10><tr>    <td class=codetable>
<pre>LRESULT CALLBACK WinProcedure 
    (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_DESTROY:
            ::PostQuitMessage (0);
            return 0;
    }
    return ::DefWindowProc (hwnd, message, wParam, lParam );
}</pre>
</td></tr></table><!-- End Code -->


<p>It doesn抰 do much in this particular program. It only handles one message, <var>WM_DESTROY</var>, that is sent to the window when it is being destroyed. At that point the window has already been closed--all we have to do is to terminate <var>WinMain</var>. We do it by posting the final <i>quit</i> message. We also pass the return code through it--zero in our case. This message will terminate the message loop and control will be returned to <var>WinMain</var>.

<h3>Encapsulation</h3>

<p>A lot of Windows APIs take a large number of arguments. For instance, when you create a window, you have to be able to specify its position, size, style, title, and so on... That's why <var>CreateWindowEx</var> takes 12 arguments. <var>RegisterClassEx</var> also requires 12 parameters, but they are combined into a single structure, <var>WNDCLASSEX</var>. As you can see, there is no consistency in the design of Windows API.

<p>Our approach to encapsulating this type of APIs is to create a C++ class that combines all the arguments in one place. Since most of these arguments have sensible defaults, the constructor should initialize them appropriately. These parameters that don't have natural defaults are passed as arguments to the constructor. The idea being that, once an object of such a class is constructed, it should be usable without further modification. However, if modifications are desired, they should be done by calling appropriate methods.

<p>For instance, if we are to develop the class <var>WinMaker</var> into a more useful form, we should add methods such as <var>SetPosition</var> and <var>SetSize</var> that override the default settings for <var>_x</var>, <var>_y</var>, <var>_width</var> and <var>_height</var>.

<p>Let's analyze the two classes, <var>WinClassMaker</var> and <var>WinMaker</var> in this context. <var>WinClassMaker</var> encapsulates the API <var>RegisterClassEx</var>. The argument to this API is a structure which we can embed directly into our class. Three of the ten parameters--window procedure, class name and program instance--cannot be defaulted, so they are passed in the constructor. The window background color is normally defaulted to whatever the current system setting is--that's the COLOR_WINDOW constant. The mouse cursor in most cases defaults to whatever the system considers an arrow--that's the <var>IDC_ARROW</var> constant. The size of the structure must be set to <var>sizeof (WNDCLASSEX)</var>. The rest of the parameters can be safely set to zero. We don't have to do anything else before calling <var>WinClassMaker::Register</var>. Of course, in a more sophisticated program, we might want to modify some of these settings, and we would most certainly add methods to do that. We'll talk about it later.

<p>In a similar way, the API <var>CreateWindowEx</var> is encapsulated in the class <var>WinMaker</var>. The non-defaultable parameters are the class name, the program instance and the title of the window. This time, however, we might want to call <var>WinMaker::Create</var> multiple times in order to create more than one window. Most likely these windows would have different titles, so we pass the title as an argumet to <var>Create</var>.

<p class=summary>To summarize, in the main procedure, your program creates a window of a particular class and enters the message processing loop. In this loop, the program waits idly for a message from Windows. Once the message arrives, it dispatches is back to Windows. The system then calls your Window procedure with the same message. You either process it yourself, or use the default processing. After returning from Window procedure, control goes back to the message loop and the whole process repeats itself. Eventually a "quit" message is posted and the loop ends.</p>

</table>
</html>

⌨️ 快捷键说明

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