Win32 Application Hello World 详细注释
2016-12-22 22:31
411 查看
// win32project.cpp : Defines the entry point for the application. // #include "stdafx.h" #include "win32project.h" #define MAX_LOADSTRING 100 // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name // Forward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY _tWinMain(HINSTANCE hInstance,//当前实例句柄 HINSTANCE hPrevInstance,//NULL,为了兼容 LPTSTR lpCmdLine,//该字符串包含传递给应用程序的命令行参数 int nCmdShow)//指定程序的窗口应该如何显示 { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: Place code here. MSG msg; HACCEL hAccelTable; // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); //将szTitle赋值为字符串IDS_APP_TITLE LoadString(hInstance, IDC_WIN32PROJECT, szWindowClass, MAX_LOADSTRING); //将szWindowClass赋值为字符串IDC_WIN32PROJECT MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32PROJECT)); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) //编写消息循环代码 { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); //请求Windows为那些与键盘有关的消息做一些转换工作 DispatchMessage(&msg); //请求Windows分派消息到窗口过程,由窗口过程函数对消息进行处理 } } return (int) msg.wParam; } // // FUNCTION: MyRegisterClass() // // PURPOSE: Registers the window class. // // COMMENTS: // // This function and its usage are only necessary if you want this code // to be compatible with Win32 systems prior to the 'RegisterClassEx' // function that was added to Windows 95. It is important to call this function // so that the application will get 'well formed' small icons associated // with it. // ATOM MyRegisterClass(HINSTANCE hInstance) //设计窗口类 { WNDCLASSEX wcex; //创建WNDCLASSEX类型的对象 wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; //设置窗口的样式 wcex.lpfnWndProc = WndProc; //回调函数 wcex.cbClsExtra = 0; //可以请求额外空间,一般不需要 wcex.cbWndExtra = 0; wcex.hInstance = hInstance; //指定当前应用程序的实例句柄 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32PROJECT));//指定窗口类的图标句柄 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); //指定窗口类的光标句柄 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); //指定窗口类的背景画刷句柄 //wcex.hbrBackground = static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)); //BLACK_BRUSH,DKGRAY_BRUSH, GRAY_BRUSH wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WIN32PROJECT);//lpszMenuName是一个以空终止的字符串,指定菜单资源的名字。 //如果该窗口没有菜单,则应该将其设为0. wcex.lpszClassName = szWindowClass; //指定窗口类的名字 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); //标识某个窗口最小化时显示的图标 return RegisterClassEx(&wcex);//调用RegisterClassEx()函数向系统注册窗口类 } // // FUNCTION: InitInstance(HINSTANCE, int) // // PURPOSE: Saves instance handle and creates main window // // COMMENTS: // // In this function, we save the instance handle in a global variable and // create and display the main program window. // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // Store instance handle in our global variable //创建窗口 hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); //初始化窗口 UpdateWindow(hWnd); //通知Windows应用程序重绘客户区 return TRUE; } // // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) // // PURPOSE: Processes messages for the main window. // // WM_COMMAND - process the application menu // WM_PAINT - Paint the main window // WM_DESTROY - post a quit message and return // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) //窗口过程函数 { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: Add any drawing code here... TextOut(hdc,100,100,L"Visual C++ 2010",sizeof("Visual C++ 2010")-1); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_LBUTTONDOWN: MessageBox(hWnd, TEXT("单击鼠标左键"),TEXT("提示"),0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // Message handler for about box. INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; }
Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->//一个简单的Win32应用程序 //通过这个简单的实例讲解Windows消息是如何传递的 #include "stdafx.h" #include <windows.h> //声明窗口过程函数 LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); //定义一个全局变量,作为窗口类名 TCHAR szClassName[] = TEXT("SimpleWin32"); //应用程序主函数 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow) { //窗口类 WNDCLASS wndclass; //当窗口水平方向的宽度和垂直方向的高度变化时重绘整个窗口 wndclass.style = CS_HREDRAW|CS_VREDRAW; //关联窗口过程函数 wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance;//实例句柄 wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);//图标 wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);//光标 wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//画刷 wndclass.lpszMenuName = NULL;//菜单 wndclass.lpszClassName = szClassName;//类名称 //注册窗口类 if(!RegisterClass (&wndclass)) { MessageBox (NULL, TEXT ("RegisterClass Fail!"), szClassName, MB_ICONERROR); return 0; } //建立窗口 HWND hwnd; hwnd = CreateWindow(szClassName,//窗口类名称 TEXT ("The Simple Win32 Application"),//窗口标题 WS_OVERLAPPEDWINDOW,//窗口风格,即通常我们使用的windows窗口样式 CW_USEDEFAULT,//指定窗口的初始水平位置,即屏幕坐标系的窗口的左上角的X坐标 CW_USEDEFAULT,//指定窗口的初始垂直位置,即屏幕坐标系的窗口的左上角的Y坐标 CW_USEDEFAULT,//窗口的宽度 CW_USEDEFAULT,//窗口的高度 NULL,//父窗口句柄 NULL,//窗口菜单句柄 hInstance,//实例句柄 NULL); ShowWindow(hwnd,iCmdShow);//显示窗口 UpdateWindow(hwnd);//立即显示窗口 //消息循环 MSG msg; /* GetMessage()从消息队列中取消息,对取出的消息进行转换(TranslateMessage), 对于能够将虚拟键码转化成字符码的消息,会在消息队列里放一条WM_CHAR消息, 最后将消息发送到相应的消息处理函数进行处理。 循环执行这个处理过程,直到收到WM_QUIT消息,才退出循环,结束程序。 */ while(GetMessage(&msg,0,0,0))//从消息队列中取消息 { TranslateMessage (&msg); //转换消息 DispatchMessage (&msg); //派发消息 } return msg.wParam; /*---------------GetMessage--------------------------------- GetMessage 函数原型: BOOL GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax); 参数: lpMsg:一个指向MSG结构的指针,该结构用于存放从消息队列里取出的消息。 hWnd:窗口句柄。如果该参数是非零值,则GetMessage只检索该窗口(也包括其子窗口)消息,如果为零,则GetMessage检索整个进程内的消息。 wMsgFilterMin:指定被检索的最小消息值,也就是消息范围的下界限参数。 wMsgFilterMax:上界限参数。如果wMsgFilterMin和wMsgFilterMax都为零,则不进行消息过滤,GetMessage检索所有有效的消息。 返回值: GetMessage检索到WM_QUIT消息,返回值是零;其它情况,返回非零值。 函数功能: 这个API函数用来从消息队列中“摘取”一个消息,放到lpMsg所指的变量里。(注:如果所取窗口的消息队列中没有消息,则程序会暂停在GetMessage(…) 函数里,不会返回。) 再通俗一点讲解GetMessage函数: 当程序执行GetMessage()的时候,会检查消息队列,如果有消息在消息队列里,它取出该消息,将该消息填充到lpMsg所指的MSG结构,并返回TRUE值。如果此时消息队列里没有消息(消息队列为空),它会将线程阻塞,也就是将控制权交给系统,直到消息队列中有内容时,才唤醒线程继续执行。 对于GetMessage()函数,还有一点需要说明,就是当从消息队列中取出的消息是WM_QUIT时,函数返回值是0。我们一般利用这一点退出消息循环,结束程序。 ---------------------------------------------------------------*/ /*------------------TranslateMessage--------------------- TranslateMessage 函数原型: BOOL TranslateMessage(CONST MSG*lpMsg); 参数: IpMsg:指向MSG结构的指针,该结构是函数GetMessage或PeekMessage从消息队列里取得的消息。 函数功能: 该函数将虚拟键消息转换为字符消息。字符消息被寄送到调用线程的消息队列里,当下一次线程调用函数GetMessage或PeekMessage时被读出。 什么是虚拟键码呢?Windows为了方便输入管理,减少程序对设备的依赖性,将键盘上所有的按键都用一个两位十六进制数对应,这些数称为虚拟键码。虚拟键码一般以VK_开头,如:Esc键对应的虚拟键码是VK_ESCAPE;空格键对应的虚拟键码是VK_SPACE;VK_LWIN与左边的Windows徽标键相对应。 当一个按键被按下时,会触发WM_KEYDOWN消息, WM_KEYDOWN消息的wParam参数值就是虚拟键值。通过这个值就可以判断哪个键被按下了。 为什么我们要把虚拟键码转换为字符码呢? 比如我们按下了‘A’键,此时我们得到的字符可能是‘A’,也可能是小写的‘a’,这由当时的大写状态(Caps Lock)以及是否同时按下了Shift键有关。TranslateMessage()函数的作用就是不用我们考虑这些问题,而是根据这些情况,自动返回一个ASCII码值,以方便用户使用。 并不是所有的虚拟键码值都会Translate成字符码。字母、数字键都有字符码相对应,而像方向箭头键、F1—F12功能键这些按键就没有字符码相对应。当虚拟键码需要转化成字符码时,TranslateMessage()函数就在消息队列里放一条WM_CHAR消息,WM_CHAR消息的wParam参数值就是转换后的ASCII码值。 -------------------------------------------*/ /*--------------------DispatchMessage------------------- DispatchMessage 函数原型: LONG DispatchMessage(CONST MSG *lpmsg); 函数功能: 它的作用很简单,就是分派消息到窗口的消息处理函数去执行。 -------------------------------------------*/ /*-----------------PeekMessage------------- PeekMessage 函数原型: BOOL PeekMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax,UINT wRemoveMsg); 参数: lpMsg、hWnd、wMsgFilterMin、wMsgFilterMax这四个参数的意义和GetMessage对应参数的意义相同,在此不再赘述。 wRemoveMsg:这个参数决定读消息时是否删除消息,可选值有PM_NOREMOVE和PM_REMOVE。如果您选PM_NOREMOVE,执行该函数后消息仍然留在消息队列(我称为读消息);如果您选PM_REMOVE,执行该函数后将在消息队列中移除该消息(同GetMessage())。 返回值: 消息队列中有消息,返回值为TRUE;消息队列中没有消息,返回值为FALSE。 函数功能: PeekMessage()也是从消息队列中取消息,但它是GetMessage()不同,主要在以下两点: (一)、GetMessage()只能从消息队列中取走消息,也就是说,GetMessage()执行后,该消息将从消息队列中移除。 PeekMessage()可以从消息队列中取走消息。也可以读消息,让消息继续留在消息队列里。 (二)、当消息队列中没有消息时,GetMessage()将会阻塞线程,等待消息;而PeekMessage()与GetMessage()不同,它执行后会立刻返回,消息队列中有消息时,返回值为TRUE;消息队列中没有消息时,返回值为FALSE。 ------------------------------------*/ /*-------------------PeekMessage版的消息循环--------------------------- //消息循环 MSG msg; while(true) { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) //从消息队列中取消息 { if(msg.message == WM_QUIT) break; TranslateMessage (&msg); //转换消息 DispatchMessage (&msg); //派发消息 } else WaitMessage(); } //End of while(true) */ /*------------------WaitMessage-------------------------- WaitMessage 函数原型: BOOL WaitMessage(VOID); 函数功能: 这个函数的作用是当消息队列中没有消息时,将控制权交给其它线程。该函数将会使线程挂起,直到消息队列中又有新消息。 这个函数专门和PeekMessage配合使用,当消息队列中没有消息时,挂起线程,等待消息队列中新消息的到来,这样可以减轻CPU的运算负担。 --------------------------------------------------*/ } //消息处理函数 //参数:窗口句柄,消息,消息参数,消息参数 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { //处理感兴趣的消息 switch (message) { case WM_DESTROY: //当用户关闭窗口,窗口销毁,程序需结束,发退出消息,以退出消息循环 PostQuitMessage(0); return 0; } //其他消息交给由系统提供的缺省处理函数 return ::DefWindowProc (hwnd, message, wParam, lParam); }
相关文章推荐
- prjHelloWorld - Win32 Application Hello World 代码解析 - VC++6 - HackerJLY
- win32SDK的hello,world程序(二)
- 7.Struts 2 Hello World - Developing Hello World Application
- PacMan开发-Win32的"HelloWorld"&WinMain()函数
- Spring 3 MVC: Create Hello World Application In Spring 3.0 MVC
- win32 asm Hello World Demo
- 8.Writing JSP, Java and Configuration for Hello World Application
- PacMan开发-Win32的"HelloWorld"&WinMain()函数
- IDEA建立Spring MVC Hello World 详细入门教程
- win32 asm Hello World Demo
- Installing Android Studio IDE in Ubuntu | Fedora – Hello World Application
- win32窗口程序的详细注释
- PacMan开发-Win32的"HelloWorld"&MyRegisterClass()函数
- Spring 3 MVC Framework Based Hello World Web Application Example Using Maven, Eclipse IDE And Tomcat
- Spring 3 mvc hello world application with maven and jstl
- PacMan开发-Win32的"HelloWorld"&MyRegisterClass()函数
- Eclipse使用maven搭建简单spring boot application Hello World
- Java SE series:1. environment configure and Hello world! [We use compiler and packager to create an application!]
- Windows下qt的环境配置及运行一个c++"hello world"实例详细步骤
- RESTEasy + JBOSS 7 Hello world application---reference