【转】 WinMain函数

原文地址:http://blog.csdn.net/dylanlrp/article/details/5724835

 

 

1、WinMain()函数     首先,必须要声明一个WinMain()函数(为了简明起见,这里先不讨论_tWinMain这个宏,也不考虑Unicode的问题),它的原型在Windows.h中定义:

int WINAPI WinMain(HINSTANCE hInstance, //程序当前实例的句柄,以后随时可以用GetModuleHandle(0)来获得 

                                HINSTANCE hPrevInstance,   //这个参数在Win32环境下总是0,已经废弃不用了   

                                char * lpCmdLine, //指向以/0结尾的命令行,不包括EXE本身的文件名,

                                                              //以后随时可以用GetCommandLine()来获取完整的命令行   

                                int nCmdShow      //指明应该以什么方式显示主窗口

);

声明,并且实现这个函数,让Linker程序可以找到它,让编程语言的运行时刻库在完成一些必要的初始化工作后,能够正确地调用它。所以,认为它就是程序的入口点,也是一种简单的“抽象法则”。

在这个入口点函数中,需要按顺序做下面几件事(如果是基于事先设计并存放在资源里的对话框的程序,稍有不同,以后再说):

    (1)用RegisterClassEx函数登记一个独一无二的Class

(2)用CreateWindowEx函数创建一个主窗口

(3)进入一个”消息循环“,直到收到WM_QUIT消息

(4)从WinMain函数返回       基本上所有的流程都如出一辙,所以完全可以设计出一个“Template模式”出来重用,让以后的程序直接从某个抽象基类继承,实现基类所需的虚方法就可以了.

2、窗口消息回调函数

    简单地说,回调(Callback)函数就是一个按规定原型实现的一个函数,让别人来调用。比如说,每个窗口都有一个窗口类(用

RegisterClassEx登记的Class,或者系统缺省已实现的Class),每个窗口类有一个回调函数,当窗口收到WIndows消息的时候,就会去调用这个回调函数,而这个回调函数的代码是程序员自己写的,用来根据实际情况处理不同的窗口消息。

 

3、登记窗口类     在创建主窗口之前,一定要先用RegisterClassEx这个API函数登记一个类,类名必须是独一无二的,所以一般都用GUID字串来做类名。

 

4、创建主窗口

 

5、消息循环     消息循环很简单,仅当GetMessage这个API函数返回FALSE时,才退出循环。而GetMessage()仅当处理到消息队列中的WM_QUIT消息时才会返回FALSE。

 

下面代码生成了一个title为Demo的窗口。

#include <sstream>
#include <Windows.h>
//独一无二的类名,一般用GUID字串,以免与其他程序的类名重复
static const char * CLASS_NAME = "{198CEAB2-AD78-4ed3-B099-247639080CB0}";

/************************************************************************
    回调函数,当主窗口收到任何Windows消息时被调用
************************************************************************/
LRESULT CALLBACK onMainWndMessage(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{
    switch (msg) {
        case WM_DESTROY:
            PostQuitMessage(0); //如果是“窗口销毁”事件,则应该在消息队列中投递 
            break;              //一个WM_QUIT消息,使GetMessage()返回FALSE   
        default:        
            return DefWindowProc(wnd, msg, wParam, lParam);
    }    
    return 0;
}

/************************************************************************    
登记自己的窗口类
************************************************************************/
bool registerMyClass() 
{
    WNDCLASSEX  wce = {0};    
    wce.cbSize = sizeof(wce);    
    wce.style  = CS_VREDRAW | CS_HREDRAW;    
    wce.lpfnWndProc = &onMainWndMessage;  //指明回调函数    
    wce.hInstance = GetModuleHandle(0);    
    wce.hIcon = LoadIcon(0, MAKEINTRESOURCE(IDI_WINLOGO));    
    wce.hCursor = LoadCursor(0, MAKEINTRESOURCE(IDC_ARROW));    
    wce.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_BTNFACE+1);    
    wce.lpszClassName = CLASS_NAME; //独一无二的类名    
    wce.hIconSm = wce.hIcon;    
    return 0 != RegisterClassEx(&wce);
}
/************************************************************************    
创建并显示主窗口
************************************************************************/
bool createMyWindow(int cmdShow) 
{    
    HWND mainWnd = CreateWindowEx(0, CLASS_NAME, "Demo", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, GetModuleHandle(0), 0);   
    if (0 != mainWnd) {       
        ShowWindow(mainWnd, cmdShow);        
        UpdateWindow(mainWnd);        
        return true;    
    } else {
        return false;   
    }
}
/************************************************************************    
消息循环
************************************************************************/
int messageLoop() 
{    
    MSG msg;  
    while (GetMessage(&msg, 0, 0, 0)) {        
        TranslateMessage(&msg);        
        DispatchMessage(&msg);    
    }    
    return static_cast<int>(msg.wParam);
}




/************************************************************************
    WinMain,程序入口
************************************************************************/
int WINAPI WinMain(HINSTANCE, HINSTANCE, char *, int cmdShow) 
{    
    if (registerMyClass() && createMyWindow(cmdShow)) {
        return messageLoop();    
    } else {
        std::ostringstream msg;        
        msg << "创建主窗口失败,错误代码:" << GetLastError();        
        MessageBoxA(0, msg.str().c_str(), 0, MB_OK | MB_ICONSTOP);       
        return 0;
    }
} 

 

posted @ 2013-12-22 22:31  felove  阅读(299)  评论(0)    收藏  举报