Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1363648
  • 博文数量: 118
  • 博客积分: 3888
  • 博客等级: 中校
  • 技术积分: 2940
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-10 18:15
个人简介

一看二做三总结

文章分类

全部博文(118)

分类:

2007-03-18 15:39:57

    习惯了VC的MFC框架的简洁与方便,却一直没有自己实现过windows下的Hello World程序,未免是一大遗憾。最近在学习制作游戏引擎时顺道学了一下,发现也是挺方便的,下面就对自己的学习进行一个总结。大部分的内容来自MSDN文档的A Generic Win32 Sample Application。我做了适当的简化与调整,以真实反映自己的实现过程。
 
1、入口函数(主函数):
    正像DOS需要一个入口函数main一样,在Windows下一样需要一个入口函数。C++在windows下的默认入口函数为WinMain(),所以可以据此写出最简单的windows函数:

//test001.cpp
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                 LPSTR lpCmdLine, int nShowCmd)
{
    return 0;
}

    windows.h文件必须加入
    这个函数简单到没有任何输出与显示,但却是可以运行的,也就是说它也是一个完整的程序,只是没有任何意义。
   注意:为了使得VC++编译起能够编译该程序,需要把Project->Setting0->Link->Project Option 中的Subsystem:console 改为Subsystem:windows
 
2、窗口的实现:
(1) 填充WNDCLASSEX结构体并向windows注册该结构体
    利用RegisterEx()函数把主窗体类向windows操作系统注册。
 

typedef struct _WNDCLASSEX {
    UINT cbSize;
    UINT style;
    WNDPROC lpfnWndProc;
    int cbClsExtra;
    int cbWndExtra;
    HANDLE hInstance;
    HICON hIcon;
    HCURSOR hCursor;
    HBRUSH hbrBackground;
    LPCTSTR lpszMenuName;
    LPCTSTR lpszClassName;
    HICON hIconSm;
} WNDCLASSEX;

 

ATOM RegisterClassEx(
  CONST WNDCLASSEX *lpwcx
// address of structure with class data
);

 
(2)消息获取与分派
    WNDCLASSEX结构体中的WNDPROC是一个指向一个回调函数的指针,当窗体接到windows系统传来的消息的时候,它会把该消息送到这个函数中去处理,这一过程是由如下三个函数实现的:

   PeekMessage( &msg, NULL, 0, 0 ,PM_REMOVE ); //获得Message
   TranslateMessage( &msg ); //把Virtul-Key消息翻译为字符消息
   DispatchMessage( &msg ); //把Messgae发送给窗口函数

   //本例中为WNDCLASSEX结构体中指定的回调函数
 
(3)消息处理
   消息处理程序在WNDCLASEX结构体直盯盯回调函数MainProc()中,其中最重要的是WM_PAINT与WM_DESTORY消息。WM_PAINT消息处理的是窗口重绘函数。默认情况下他会不停的触发,所以需要调用函数BeginPaint(),该函数使得系统只有在窗口产生了变化的时候才会重绘。WM_DESTORY消息用于结束程序,当窗口被关闭时会产生该消息。它需要调用PostQuitMessage()函数,这个函数会发送WM_QUIT消息,用于结束消息循环,退出程序。另外对于不需要特殊处理的消息,可以利用 DefWindowPro()函数都交给系统处理。
 

//test001.cpp

#include <windows.h>
#include "Resource.h"

LRESULT CALLBACK MainProc(
  HWND hWnd,
// handle to window
  UINT msg,
// message
  WPARAM wParam,
// first message parameter
  LPARAM lParam
// second message parameter
)
{
   PAINTSTRUCT ps;
   HDC hDC;

   switch( msg)
   {
      case WM_PAINT:
         hDC = BeginPaint( hWnd, &ps );
         TextOut( GetDC(hWnd), 10, 10, "Hello, World!", 13 );
         EndPaint( hWnd, &ps );
         break;
      case WM_DESTROY:
         PostQuitMessage( 0 );
         break;
/**************************************************************\
* Let the default window proc handle all other messages *
\**************************************************************/

      default:
         return( DefWindowProc( hWnd, msg, wParam, lParam ));
   }
   return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                 LPSTR lpCmdLine, int nShowCmd)
{


    WNDCLASSEX wndClass;
    wndClass.lpszClassName = "Test01";
    wndClass.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC;
    wndClass.hInstance = hInstance;
    wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wndClass.hCursor = LoadCursor(NULL, IDC_CROSS);
    wndClass.cbClsExtra = 0;
    wndClass.cbWndExtra = 0;
    wndClass.lpszMenuName = NULL;
    wndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TEST_001));
    wndClass.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TEST_002));
    wndClass.lpfnWndProc = MainProc;
    wndClass.cbSize = sizeof(WNDCLASSEX);

    if (!RegisterClassEx(&wndClass))
    {
        return FALSE;
    }
    HWND hWindow;
    hWindow = CreateWindow("Test01", "Test01",        

                   WS_OVERLAPPEDWINDOW|WS_HSCROLL|WS_VSCROLL,

                   100, 100,00,350, NULL, NULL, hInstance, NULL);
    ShowWindow(hWindow, nShowCmd);
    UpdateWindow(hWindow);

    MSG msg;
    while (TRUE)
    {
        PeekMessage( &msg, NULL, 0, 0 ,PM_REMOVE );
        if ( msg.message == WM_QUIT )
        {
            break;
        }
        else
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
    }
    return 0;
}

 
 
3、加入图标资源
    各种资源都是通过以下两个文件实现的。Resource.h文件加入了两个资源ID,而test01.h文件则对这两个资源ID指向的资源进行了具体描述,其它入对话框资源是使用相同方式加入的

// Resource.h
#define IDI_TEST_001 0001 // Big Icon

#define IDI_TEST_002 0002 // Small Icon

 

// test001.rc
#include "resource.h"


IDI_TEST_001 ICON DISCARDABLE "logo.ico"
IDI_TEST_002 ICON DISCARDABLE "logo_sm.ico"

 
    把图标加入到窗口类时使用了一个宏定义:

#define MAKEINTRESOURCE(i) (LPTSTR) ((DWORD) ((WORD) (i)))

    该宏定义把一个整形数值(资源ID实际上就是一个整形值的宏定义)转化为与win32资源管理函数兼容的资源类型。
 
    上面的程序就完成了一个显示Hello World 窗口的win32程序
阅读(4398) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~