第一个windows窗口程序
创建一个窗口程序的空项目,或者
创建一个控制台空项目,调整下面的选项:
#include <Windows.h>int WINAPI WinMain(HINSTANCE hInstance, //实例句柄HINSTANCE hPreInstance, //没有用了LPSTR szCmd, //命令行参数int nShow //命令行参数){MessageBox(0, L"你好", L"友情提示", 0);return 0;}
在windows下编程,有两个问题需要提前了解:
数字转字符串
int WINAPI WinMain(HINSTANCE hInstance, //实例句柄HINSTANCE hPreInstance, //没有用了LPSTR szCmd, //命令行参数int nShow //命令行参数){//想要将nNum的值,用MessageBox显示出来。//数字转字符串int nNum = 100;char buf[100] = {};sprintf_s(buf, "%d", nNum);MessageBoxA(0, buf, "友情提示", 0);return 0;}
下来自己去试一试字符串转成数字。
sscanf
字符串转成数字
A版和W版
- 所有的字符串相关的API函数,都分成两个版本:A版和W版
 
int WINAPI WinMain(HINSTANCE hInstance, //实例句柄HINSTANCE hPreInstance, //没有用了LPSTR szCmd, //命令行参数int nShow //命令行参数){//想要将nNum的值,用MessageBox显示出来。//数字转字符串int nNum = 100;char buf[100] = {};wchar_t buf2[100] = {};sprintf_s(buf, "%d", nNum);swprintf_s(buf2, L"%d", nNum);MessageBoxA(0, buf, "友情提示", 0);MessageBoxW(0, buf2, L"友情提示", 0);return 0;}
T版
一般我们都使用T版函数
#include <Windows.h>#include <stdio.h>#include <tchar.h>int WINAPI WinMain(HINSTANCE hInstance, //实例句柄HINSTANCE hPreInstance, //没有用了LPSTR szCmd, //命令行参数int nShow //命令行参数){//想要将nNum的值,用MessageBox显示出来。//数字转字符串int nNum = 100;char buf[100] = {};wchar_t buf2[100] = {};sprintf_s(buf, "%d", nNum);swprintf_s(buf2, L"%d", nNum);MessageBoxA(0, buf, "友情提示", 0);MessageBoxW(0, buf2, L"友情提示", 0);//t版函数TCHAR buf3[100] = { _T("helloworld") };_stprintf_s(buf3, _T("%d"), nNum);MessageBox(0, buf3, _T("友情提示"), 0);return 0;}
asc和unicode之间的转换。
// 宽字符转换为多字符(Unicode --> ASCII)#define WCHAR_TO_CHAR(lpW_Char, lpChar) \WideCharToMultiByte(CP_ACP, NULL, lpW_Char, -1,lpChar, _countof(lpChar), NULL, FALSE);// 多字符转换为宽字符(ASCII --> Unicode)#define CHAR_TO_WCHAR(lpChar, lpW_Char) \MultiByteToWideChar(CP_ACP, NULL, lpChar, -1,lpW_Char, _countof(lpW_Char));
在windows下输出调试信息:
bool _trace(const TCHAR *format, ...) //变参函数{TCHAR buffer[1000];va_list argptr;va_start(argptr, format);//将格式化信息写入指定的缓冲区wvsprintf(buffer, format, argptr);va_end(argptr);//将缓冲区信息输出OutputDebugString(buffer);return true;}int WINAPI WinMain(HINSTANCE hInstance, //实例句柄HINSTANCE hPreInstance, //没有用了LPSTR szCmd, //命令行参数int nShow //命令行参数){int nNum = 100;_trace(_T("这个数字为%d"), nNum);return 0;}

我们也可以自己封装带格式控制符的Messagebox
bool _MyMessageBox(const TCHAR *format, ...) //变参函数{TCHAR buffer[1000];va_list argptr;va_start(argptr, format);//将格式化信息写入指定的缓冲区wvsprintf(buffer, format, argptr);va_end(argptr);//将缓冲区信息输出MessageBox(0,buffer,_T("提示"),0);return true;}int WINAPI WinMain(HINSTANCE hInstance, //实例句柄HINSTANCE hPreInstance, //没有用了LPSTR szCmd, //命令行参数int nShow //命令行参数){int nNum = 100;_MyMessageBox(_T("这个数字为%d"), nNum);return 0;}
关于windows程序的错误码:
int WINAPI WinMain(HINSTANCE hInstance, //实例句柄HINSTANCE hPreInstance, //没有用了LPSTR szCmd, //命令行参数int nShow //命令行参数){HANDLE h = GetStdHandle(100);int nError = GetLastError();//这个函数能够获取到最近一次调用的API的错误码_MyMessageBox(_T("错误码为:%d"), nError);return 0;}

在调试的时候,快速监视到错误码的方法:
注意是:err,hr
英文逗号逗号逗号
制作一个能够解析错误码的工具,能够提供出错的具体位置:
#define CHAR_TO_WCHAR(lpChar, lpW_Char) \MultiByteToWideChar(CP_ACP, NULL, lpChar, -1, \lpW_Char, _countof(lpW_Char));void MyGetErrorInfo(LPCTSTR lpErrInfo,UINT unErrCode,TCHAR* tFile,UINT unLine) // unLine=__LINE__{LPTSTR lpMsgBuf = nullptr;WCHAR szMessage[128] = { 0 };WCHAR szCaption[128] = { 0 };//这个函数能够将错误码解析为错误信息FormatMessage(0x1300, NULL, unErrCode,0x400, (LPTSTR)&lpMsgBuf, 64, NULL);swprintf_s(szMessage, 128,L"Error_0x%08X:%s", unErrCode, lpMsgBuf);swprintf_s(szCaption, 128,L"%s:%s:(Error Line:%05d)", lpErrInfo, tFile, unLine);MessageBox(NULL, szCaption, szMessage , MB_OK);}int WINAPI WinMain(HINSTANCE hInstance, //实例句柄HINSTANCE hPreInstance, //没有用了LPSTR szCmd, //命令行参数int nShow //命令行参数){HANDLE h = GetStdHandle(100);//1 获得错误码int nError = GetLastError();//2 得到出错的文件路径wchar_t buf[100] = {};CHAR_TO_WCHAR(__FILE__, buf);//3 输出错误信息MyGetErrorInfo(_T("十五派友情提示您:"), nError, buf,__LINE__-1);return 0;}
第一个窗口程序:
#include <Windows.h>#include <tchar.h>//int WinMain(// HINSTANCE hInstance,// HINSTANCE hPreInstance,// LPSTR szCmd,// int nShow//);//int wWinMain(// HINSTANCE hInstance,// HINSTANCE hPreInstance,// LPWSTR szCmd,// int nShow//);LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam);int WINAPI _tWinMain(HINSTANCE hInstance,HINSTANCE hPreInstance,LPTSTR szCmd,int nShow){//1 设计窗口类//UINT style;//WNDPROC lpfnWndProc;//int cbClsExtra;//int cbWndExtra;//HINSTANCE hInstance;//HICON hIcon;//HCURSOR hCursor;//HBRUSH hbrBackground;//LPCWSTR lpszMenuName;//LPCWSTR lpszClassName;WNDCLASS wc;wc.style = CS_VREDRAW | CS_HREDRAW;//类风格wc.lpfnWndProc = WndProc;//回调函数的地址(重要)wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hInstance = hInstance;//实例句柄,代表此程序wc.hIcon = 0; //类图标wc.hCursor = 0; //类光标wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);wc.lpszMenuName = 0;wc.lpszClassName = L"15PB";//2 注册窗口类RegisterClass(&wc);//3 创建窗口HWND hWnd = CreateWindow(L"15PB", //类名L"第一个窗口", //窗口名WS_OVERLAPPEDWINDOW,//重叠窗口风格100, 100, 400, 600, //位置和大小NULL, //父窗口句柄NULL, //菜单句柄hInstance, //实例句柄NULL //附加信息);//4 更新显示窗口ShowWindow(hWnd, SW_SHOW);UpdateWindow(hWnd);//5 实现消息循环MSG msg = {};// 5.1 获取消息//GetMessage得到WM_QUIT消息的时候,会返回Falsewhile (GetMessage(&msg, 0, 0, 0)){// 5.2 转换消息 将WM_KEYDOWN转换WM_CHARTranslateMessage(&msg);// 5.3 派发消息DispatchMessage(&msg);}return 0;}LRESULT CALLBACK WndProc(HWND hWnd,UINT uMessage,WPARAM wParam,LPARAM lParam){switch (uMessage){case WM_CLOSE:PostQuitMessage(0);//会发出一个WM_QUIT消息break;default:break;}return DefWindowProc(hWnd, uMessage, wParam, lParam);}
常见的消息处理:
WM_CLOSE       窗口关闭的消息
WM_DESTORY  窗口销毁的消息
WM_KEYDOWN 键盘按下的消息
WM_CHAR         字符按键消息
WM_LBUTTONDOWN   鼠标左键单击消息
WM_MOVING                窗口移动消息
WM_SIZE                       窗口大小改变的消息
需要用到的一个函数:GetClientRect                 获取窗口的大小
LRESULT CALLBACK WndProc(HWND hWnd,UINT uMessage,WPARAM wParam,LPARAM lParam){switch (uMessage){case WM_CREATE://一般进行一些初始化的操作break;case WM_DESTROY:_trace(L"接到了wm_destory消息\n");PostQuitMessage(0);//会发出一个WM_QUIT消息break;case WM_CLOSE:_trace(L"接到了wm_close消息\n");break;case WM_KEYDOWN:_trace(L"接到了wm_keydown消息\n");_trace(L"lParam:%d,wParam:%d\n", lParam, wParam);break;case WM_CHAR://可见字符_trace(L"接到了wm_char消息\n");_trace(L"lParam:%d,wParam:%d\n", lParam, wParam);break;case WM_LBUTTONDOWN://鼠标左键单击{_trace(L"接到了wm_lbuttondown消息\n");int x = LOWORD(lParam);int y = HIWORD(lParam);_trace(L"鼠标左键点击了x:%d,y:%d\n",x,y);}case WM_SIZE://窗口大小发生改变了{_trace(L"接到了wm_size消息\n");RECT rc = {};GetClientRect(hWnd,&rc);_trace(L"鼠标左键点击了l:%d,r:%d,t:%d,b:%d\n",rc.left, rc.right,rc.top, rc.bottom);}break;default:break;}return DefWindowProc(hWnd, uMessage, wParam, lParam);}
关于PostMessage,SendMessage,自定义消息
#define WM_MYMESSAGE WM_USER+2LRESULT CALLBACK WndProc(HWND hWnd,UINT uMessage,WPARAM wParam,LPARAM lParam){switch (uMessage){case WM_CREATE://一般进行一些初始化的操作break;case WM_DESTROY:_trace(L"接到了wm_destory消息\n");PostQuitMessage(0);//会发出一个WM_QUIT消息break;case WM_CLOSE:_trace(L"接到了wm_close消息\n");break;case WM_KEYDOWN:_trace(L"接到了wm_keydown消息\n");_trace(L"lParam:%d,wParam:%d\n", lParam, wParam);break;case WM_CHAR://可见字符_trace(L"接到了wm_char消息\n");_trace(L"lParam:%d,wParam:%d\n", lParam, wParam);break;case WM_LBUTTONDOWN://鼠标左键单击{_trace(L"接到了wm_lbuttondown消息\n");int x = LOWORD(lParam);int y = HIWORD(lParam);_trace(L"鼠标左键点击了x:%d,y:%d\n",x,y);}case WM_SIZE://窗口大小发生改变了{_trace(L"接到了wm_size消息\n");RECT rc = {};GetClientRect(hWnd,&rc);_trace(L"鼠标左键点击了l:%d,r:%d,t:%d,b:%d\n",rc.left, rc.right,rc.top, rc.bottom);}break;case WM_MYMESSAGE:{_trace(L"接到了wm_mymessage消息\n");_trace(L"lParam:%d,wParam:%d\n", lParam, wParam);MessageBox(0, 0, 0, 0);}break;default:break;}return DefWindowProc(hWnd, uMessage, wParam, lParam);}
#define WM_MYMESSAGE WM_USER+2int main(){//FindWindowPostMessage((HWND)0x00360E7C,WM_MYMESSAGE,68, 55);}
