《Windows中心编程》ITeye - AG环亚娱乐集团

《Windows中心编程》ITeye

2019年03月10日08时18分50秒 | 作者: 辰锟 | 标签: 窗口,音讯,函数 | 浏览: 1003

主函数一般是:

/*************************************************************************

* WinMain

* 功用:程序进口点,调用InitApplication,InitInstance,进行音讯循环

* 参数:hinstance-应用程序本次运转实例

*           hPrevInstance-应用程序之前的实例,一直为NULL

*            lpCmdLine-指令行参数

*            nCmdShow-窗口显现方法,如SW_SHOW

* 回来值:失利回来FALSE

************************************************************************/

int WINAPI WinMain(HINSTANCE hinstance,

                   HINSTANCE hPrevInstance,

                   LPSTR lpCmdLine,

                   int nCmdShow)

{

    MSG msg;

    BOOL fGotMessage;

    if(!InitApplication(hinstance))     //注册窗口类

    {

        return FALSE;

    }               

    if(!InitInstance(hinstance, nCmdShow))  //创立窗口和控件子窗口

    {

        return FALSE;                           

    } 

    //音讯循环

    while((fGotMessage=GetMessage( msg, (HWND)NULL, 0, 0)) != 0

              fGotMessage != -1)

    {

        TranslateMessage( msg);

        DispatchMessage( msg);        

    }

    return msg.wParam;

    UNREFERENCED_PARAMETER(lpCmdLine);

}

 

1)注册窗口类

任何一个窗口都有必要归于一个窗口类,同一个类的窗口具有相同的窗口音讯处理进程。Windows API函数RegisterClass和RegisterClassEx能够完结窗口类的注册:

ATOM WINAPI RegisterClass(

  __in  const WNDCLASS *lpWndClass

);

ATOM WINAPI RegisterClassEx(

  __in  const WNDCLASSEX *lpwcx

);

这两个函数别离运用了WNDCLASS和WNDCLASSEX结构作为参数,其间WNDCLASS界说如下:

typedef struct tagWNDCLASS {

  UINT      style; //窗口款式,经过体系预先界说的一些常量来设置窗口的姿态

  WNDPROC   lpfnWndProc; //音讯处理函数

  int       cbClsExtra; //附加窗口类内存

  int       cbWndExtra; //附加窗口内存

  HINSTANCE hInstance; //赋值为应用程序的实例

  HICON     hIcon; //窗口的图标款式

  HCURSOR   hCursor; //窗口的鼠标款式

  HBRUSH    hbrBackground; //窗口的布景画刷,如COLOR_BACKGROUND、COLOR_WINDOW.

  LPCTSTR   lpszMenuName; //菜单名

  LPCTSTR   lpszClassName; //新建类的类名,在创立窗口时需求指定窗口所属类的类名

} WNDCLASS, *PWNDCLASS;

WNDCLASSEX结构界说如下:

typedef struct tagWNDCLASSEX {

  UINT      cbSize; //WNDCLASSEX结构的巨细

  UINT      style; //窗口款式

  WNDPROC   lpfnWndProc; //窗口音讯处理函数

  int       cbClsExtra; //附加窗口类内存

  int       cbWndExtra; //附加窗口内存

  HINSTANCE hInstance; //应用程序实例

  HICON     hIcon; //窗口图标

  HCURSOR   hCursor; //窗口鼠标

  HBRUSH    hbrBackground; //布景画刷

  LPCTSTR   lpszMenuName; //菜单资源

  LPCTSTR   lpszClassName; //窗口类名

  HICON     hIconSm; //小图标

} WNDCLASSEX, *PWNDCLASSEX;

 

实例代码中InitApplication函数注册了窗口类:

/*************************************************************

* BOOL InitApplication(HINSTANCE hinstance)

* 功用:注册主窗口类

* 参数:hinstance,应用程序本次运转实例

* 回来值:是否成功

*************************************************************/

BOOL InitApplication(HINSTANCE hinstance)

{

    //运用RegisterClassEx

    WNDCLASSEX wcx;

    //填充结构

    wcx.cbSize = sizeof(wcx);  //WNDCLASSEX结构的巨细

    wcx.style = CS_HREDRAW | CS_VREDRAW; //假如巨细改动了将重绘窗口

    wcx.lpfnWndProc = MainWndProc;       //窗口音讯处理函数

    wcx.cbClsExtra = 0;                  //无附加窗口类内存

    wcx.cbWndExtra = 0;                  //无附加窗口内存

    wcx.hInstance = hinstance;           //应用程序实例

    wcx.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_ICON_MAIN)); //图标º

    wcx.hCursor = LoadCursor(NULL, IDC_ARROW); //鼠标指针

    wcx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //布景画刷

    wcx.lpszMenuName = MAKEINTRESOURCE(IDR_MENU_MAIN); //菜单资源

    wcx.lpszClassName = "ASCEClass";  //窗口类名

wcx.hIconSm = (HICON)LoadImage(hinstance, //小图标

MAKEINTRESOURCE(IDI_ICON_MAIN),

IMAGE_ICON,

GetSystemMetrics(SM_CXSMICON),

GetSystemMetrics(SM_CYSMICON),

LR_DEFAULTCOLOR);

    //注册窗口类,并回来

    return RegisterClassEx( wcx);

}

 

2)创立窗口

WinMain主函数调用InitInstance函数完结了程序主窗口的创立,CreateWindow和CreateWindowEx是用于创立窗口的API函数。

CreateWindow函数的功用是创立一个窗口,在创立窗口前,需先注册窗口类。假如创立的窗口是体系控件,那么体系操控的类现已由体系注册好,所以不再需求注册:

HWND WINAPI CreateWindow(

  __in_opt  LPCTSTR lpClassName, //窗口所需窗口类的类名

  __in_opt  LPCTSTR lpWindowName, //窗口名,窗口有标题栏的话,将显现在上面

  __in      DWORD dwStyle, //窗口款式,窗口是否具有标题栏,是否可改动巨细,

//边框的款式等都经过这个参数设置

  __in      int x, //创立创立后的初始方位,可设为CW_USEDEFAULT,由体系来设置

  __in      int y,

  __in      int nWidth, //窗口的宽和高,以像素点为单位,相同可指定为CW_USEDEFAULT

  __in      int nHeight,

  __in_opt  HWND hWndParent, //父窗口的句柄,当窗口款式设有WS_CHILD时需设置该项

  __in_opt  HMENU hMenu, //

  __in_opt  HINSTANCE hInstance, //应用程序实例,设置为WinMain的hInstance参数

  __in_opt  LPVOID lpParam //指定相关参数,指向CREATESTRUCT结构的变量,能够为NULL

);

最常见的窗口款式:

WS_BORDER          //具有边框

WS_CAPTION        //具有标题栏

WS_CHILD     //是子窗口

WS_CHILDWINDOW  //同上

WS_HSCROLL        //具有水平滚动条

WS_MAXIMIZE //创立最大化窗口

WS_MINIMIZE       //创立最小化窗口

WS_POPUP   //顶层窗口(无父窗口,不能和WS_CHILD一起运用)

WS_SIZEBOX //具有迁延窗口边框,窗口可改动巨细

WS_SYSMENU        //窗口具有菜单(窗口有必要一起具有标题栏)

WS_TILED       //具有标题栏和边框

WS_VISIBLE    //窗口可见

WS_VSCROLL         //具有竖直滚动条

 

CreateWindow和CreateWindowEx回来值都是HWND类型。HWND是窗口句柄数据类型。在Windows体系中每个窗口都有一个句柄,一切窗口句柄都是HWND数据类型的。

WinMain函数调用InitInstance函数完结了窗口的创立:

/*************************************************************

* BOOL InitInstance(HINSTANCE hinstance, int nCmdShow)

* 功用;创立主窗口和控件

* 参数:hinstance,应用程序本次运转实例

*       nCmdShow,怎么显现

* 回来值:是否成功

*************************************************************/

BOOL InitInstance(HINSTANCE hinstance, int nCmdShow)

{

HWND hwnd;

RECT rect;

    //保存应用程序实例句柄

    hinst = hinstance;

    hwnd = CreateWindow(

           "ASCEClass", //窗口类名,运用之前注册的主窗口类

           "This’s ASCE’s Windows", //窗口名,显现在窗口标题栏上的字符串

           WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |

           WS_POPUPWINDOW, //窗口款式

           CW_USEDEFAULT,  //水平方位(默许)

           CW_USEDEFAULT,  //笔直方位(默许)

           800,            //宽

           600,            //高

           (HWND)NULL,     //无父窗口

           (HMENU)LoadMenu(hinst, MAKEINTRESOURCE(IDR_MENU_COMMAND)), //菜单

           hinstance,      //应用程序实例

           (LPVOID)NULL    //无窗口创立数据

           );

    //窗口创立是否成功

    if(!hwnd)

       return FALSE;

             //保存窗口句柄

         hwndMain = hwnd;

         //确保通用控件动态链接库现已加载

         InitCommonControls();

         //创立三种控件、子窗口

         hwndTreeView = CreateTreeView(hwndMain, "files");

         hwndListView = CreateListView(hwndMain, "processing");

         hwndEdit = CreateEdit(hwndMain, "textarea");

         //获取本窗口客户区的RECT(矩形方框的4个边界点)

         GetClientRect(hwndMain, rect);

         //设置子窗口客户区的巨细和方位

         SetWindows( rect);

         //在EDIT控件中显现文本

         ShowTextOnEdit(lpszLatin);

    //显现、改写窗口,运用WinMain函数设置的窗口显现方法

    ShowWindow(hwnd, nCmdShow);

    UpdateWindow(hwnd);

    return TRUE;

}

 

3)窗口音讯处理函数:

音讯处理函数是一个回调函数,是注册窗口类时指定,在有音讯需求处理时由体系调用。

音讯处理函数具有固定的接口方法:

LRESULT CALLBACK WindowProc(   //函数名恣意

  __in  HWND hwnd, //操作的窗口

  __in  UINT uMsg, //音讯标识符,窗口处理函数中需依据这个函数判别音讯的类型做出不同的处理

  __in  WPARAM wParam, //音讯的两个参数,依据音讯类型的不同而有不同的含义

  __in  LPARAM lParam

);

窗口处理音讯实例:

/****************************************************

* MainWndProc

* 窗口音讯处理函数

****************************************************/

LRESULT CALLBACK MainWndProc(HWND hwnd,

                             UINT uMsg,

                             WPARAM wParam,

                             LPARAM lParam)

{

         switch(uMsg)

         {

         case WM_CREATE: //窗口被创立时收到此音讯

                   break;

         case WM_PAINT: //窗口被制作时收到此音讯

                   break;

         case WM_SIZE:       //窗口巨细改动时收到此音讯

                   OnWindowResize();

                   break;

         case WM_NOTIFY:        //一般由控件发送给其父窗口,阐明控件正在进行某项窗口操作

                   OnChildWindowsNotify((PVOID)lParam);

                   break;

         case WM_DESTROY:     //窗口毁掉,单击右上角的封闭按钮会触发此音讯

                   PostQuitMessage(0);

                   break;

         case WM_COMMAND:

                   {

                            switch(LOWORD(wParam))

                            {

                                     //在“协助”菜单中挑选“关于”

                            case ID_HELP_ABOUT:

                                     {

                                               DialogBox(hinst, (LPCTSTR)IDD_DIALOG_ABOUT, hwnd, (DLGPROC)About);

                                               return 0;

                                     }

                            }

                   }

         //能够在这里处理其他音讯

         default:

                   break;

         }

         //有许多音讯未做处理,需求由默许窗口音讯处理函数来处理

         return DefWindowProc(hwnd, uMsg, wParam, lParam);

}

 

常见的窗口音讯:

WM_CLOSE   //收到此音讯时窗口应封闭

WM_CREATE          //窗口被创立时

WM_DESTROY//当窗口从界面上毁掉时(用户单击窗口右上角封闭按钮)

WM_MOVING      //窗口被移动时

WM_SIZE        //窗口巨细改动时

WM_NOTIFY         //窗口所包含的子窗口被操作时,窗口会收到此音讯

WM_COMMAND          //当菜单、按钮被操作时,窗口会收到此音讯

WM_NCLBUTTONDOWN //当用户在窗口中单击左键时,窗口会收到此小溪

WM_MOUSEHOVER   //当鼠标在窗口客户区徜徉一段时间后窗口会收到此音讯

 

重要音讯:

1)WM_NOTIFY:

当一个窗口的子窗口被操作时,该子窗口会向父窗口发送WM_NOTIFY告诉。WM_NOTIFY的lParam参数是一个指向NMHDR结构的指针:

typedef struct tagNMHDR {

  HWND     hwndFrom; //向主窗口发送此音讯的子窗口的句柄

  UINT_PTR idFrom; //子窗口的标识符

  UINT     code; //表明进行哪种操作

} NMHDR;

比方上面说到的OnChildWindowNotify函数一切到了NM_RCLICK表明右键单击;此外,还有NM_SETFOCUS(取得焦点)、NM_KEYDOWN(键盘按键)等,OnChildWindowNotify函数详细代码如下:

/*****************************************************************

* 功用:处理操控子窗口向父窗口发送的WM_NOTIFY音讯

* 参数:pParam-WM_NOTIFY的音讯参数

* 回来值:是否是Tree View发送的

******************************************************************/

BOOL OnChildWindowNotify(PVOID pParam)

{

         LPNMHDR phdr = (LPNMHDR)pParam;

         //只处理Tree View发送的Notify,其他的不予处理

         if(phdr- hwndFrom != hwndTreeView)

         {

                   return FALSE;

         }

         switch((LPNMHDR)pParam- code)

         {

                   //假如是右键单击,则调用OnRclickTree函数,弹出右键菜单

         case NM_RCLICK:

                   OnRclickTree((LPNMHDR)pParam);

                   break;

         default:

                   break;

         }

         return TRUE;

}

 

2)WM_DESTROY:

收到WM_DESTROY音讯表明用户单击窗口的封闭按钮。因而在MainWndProc函数收到WM_DESTROY音讯后,调用PostQuitMessage函数退出程序运转。当然,要退出一个进程的运转,也能够调用ExitProcess函数。

 

3)WM_COMMAND:

收到WM_COMMAND一般是由于用户经过菜单、按钮等向程序输入指令。WM_COMMAND音讯的wParam的低位WORD是表明用户单击的控件或菜单项的ID。

 

窗口会收到许多音讯,但这些音讯不一定需求处理,有些音讯或许直接由体系来处理。DefWindowProc

的效果就是处理窗口处理函数没有处理完、或许不需求处理的函数。假如在音讯处理函数中不把音讯交给DefWindowProc处理,那么对窗口的动作简直不会有呼应,包含移动窗口、封闭窗口等,甚至有许多窗口款式不能显现。

 

设置窗口方位和巨细:

上面的InitInstance函数除了完结父窗口的创立外,还创立了3个子窗口。在创立子窗口完结后,调用了SetWindows函数,代码如下:

/*************************************************************************

* 功用:本函数设置子窗口的方位和巨细

* 参数:指向表明父窗口客户区的RECT

*************************************************************************/

DWORD SetWindows(LPRECT lpRect)

{

         //Tree View

         SetWindowPos(hwndTreeView, HWND_TOP,

                   lpRect- left, lpRect- top,

                   lpRect- right * 0.3, lpRect- bottom,

                   SWP_SHOWWINDOW);

         //List View

         SetWindowPos(hwndListView, HWND_TOP,

                   lpRect- right * 0.3, lpRect- bottom * 0.7,

                   lpRect- right * 0.7, lpRect- bottom * 0.3,

                   SWP_SHOWWINDOW);

         //Edit

         SetWindowPos(hwndEdit, HWND_TOP,

                   lpRect- right * 0.3, lpRect- top,

                   lpRect- right * 0.7, lpRect- bottom * 0.7,

                   SWP_SHOWWINDOW);

         return 0;

}

上面用到的API函数是SetWindowPos:

BOOL WINAPI SetWindowPos(

  __in      HWND hWnd, //需设置的窗口句柄

  __in_opt  HWND hWndInsertAfter, //阐明窗口的层次次序,HWND_TOP表明显现在最上方

  __in      int X, //窗口的左上角地点方位和窗口的宽、高

  __in      int Y,

  __in      int cx,

  __in      int cy,

  __in      UINT uFlags //窗口巨细和方位标志,SWP_SHOWWINDOW表明窗口正常显现

);

 

不只窗口的方位和巨细能够设置,窗口简直一切特点都能够设置,包含窗口款式、音讯处理函数等。

SetWindowLong函数可完结窗口多种特点设置:

LONG WINAPI SetWindowLong(

  __in  HWND hWnd, //指明需求设置特点的窗口

  __in  int nIndex, //指明需求设置哪种特点

  __in  LONG dwNewLong //新特点值

);

nIndex常见的值有:

GWL_STYLE   //窗口款式

GWL_WNDPROC          //窗口的音讯处理函数

GWL_HINSTANCE         //应用程序实例

 

窗口显现方法:

创立好的窗口能够在屏幕上显现,也能够不在屏幕上显现,经过ShowWindow函数进行设置:

BOOL WINAPI ShowWindow(

  __in  HWND hWnd, //窗口句柄

  __in  int nCmdShow //显现的方法,如SW_HIDE、SW_SHOW,SW_MAXIMIZE等

);

 

线程音讯处理和音讯循环:

GetMessage函数是从其地点的线程的音讯行列中得到一条音讯:

BOOL WINAPI GetMessage(

  __out     LPMSG lpMsg, //指向MSG结构的指针,该结构由于存储获取的音讯

  __in_opt  HWND hWnd, //指定从哪个窗口获取音讯,1)为NULL时,表明处理归于当时线程的

//一切窗口音讯,以及线程音讯行列中hwnd为NULL的窗口音讯;

//2)为-1时,表明只处理线程音讯行列中hwnd为NULL的窗口音讯

  __in      UINT wMsgFilterMin, //获取音讯的ID编号最小值,小于这个值就不获取

  __in      UINT wMsgFilterMax //获取音讯的ID编号最大值,大于这个值就不获取

);

 

TranslateMessage函数用来把虚拟键音讯转化成字符音讯。由于Windows对一切键盘编码都选用虚拟键的界说,当按键按下时,并不得到字符音讯,需求该函数来进行转化。转化后字符音讯被传递到调用线程的音讯行列中,当下一次调用GetMessage或PeekMessage时被取出:

BOOL WINAPI TranslateMessage(

  __in  const MSG *lpMsg

);

 

DispatchMessage函数把音讯发送到窗口的音讯处理函数处:

LRESULT WINAPI DispatchMessage(

  __in  const MSG *lpmsg

);

 

Windows体系为每个线程创立音讯行列,从音讯行列中获取音讯运用GetMessage函数。也能够调用API函数将音讯添加到音讯行列中。PostMessage和SendMessage函数不同的是:PostMessage函数仅仅把音讯放置在线程的音讯行列之后就当即回来;而SendMessage函数是直接交给窗口音讯处理函数:

BOOL WINAPI PostMessage(

  __in_opt  HWND hWnd,

  __in      UINT Msg,

  __in      WPARAM wParam,

  __in      LPARAM lParam

);

 

LRESULT WINAPI SendMessage(

  __in  HWND hWnd,

  __in  UINT Msg,

  __in  WPARAM wParam,

  __in  LPARAM lParam

);

 

PostQuitMessage函数将WM_QUIT音讯音讯放置在音讯行列中,GetMessage函数在取得了WM_QUIT音讯后,会回来0,退出音讯循环。

留意,GetMessage函数仅仅获取了其地点的线程的音讯行列中的音讯,因而,在开发多线程的图形用户界面程序时,一般将一切窗口的创立放置在同一个线程,子窗口的创立最好在主窗口的音讯处理函数中,这样能确保音讯都会集中同一个线程中。假如在其他线程中需求操作界面,能够直接运用PostThreadMessage、SendMessage等函数向窗口发送自界说的音讯,然后再在窗口音讯处理函数中处理这些自界说窗口音讯时进行窗口操作。

BOOL WINAPI PostThreadMessage(

  __in  DWORD idThread,

  __in  UINT Msg,

  __in  WPARAM wParam,

  __in  LPARAM lParam

);

版权声明
本文来源于网络,版权归原作者所有,其内容与观点不代表AG环亚娱乐集团立场。转载文章仅为传播更有价值的信息,如采编人员采编有误或者版权原因,请与我们联系,我们核实后立即修改或删除。

猜您喜欢的文章