目录
在VS2019中,点击视图下的其他窗口,资源视图,就可以看到本项目的所有资源

鼠标右键添加-资源,即可添加各种类型的资源


不带资源的文件是如何编译的?

带资源的编译链接过程:


可以适应Editor查看到可执行文件的最后面就是.h的二进制文件
SendMessage:将指定的消息发送到一个或多个窗口,它调用指定窗口的窗口过程,知道该窗口过程处理完该消息后才返回
- LRESULT SendMessage(
- [in] HWND hWnd,
- [in] UINT Msg,
- [in] WPARAM wParam,
- [in] LPARAM lParam
- );
PostMessage:将消息投递到消息队列
- BOOL PostMessageA(
- [in, optional] HWND hWnd,
- [in] UINT Msg,
- [in] WPARAM wParam,
- [in] LPARAM lParam
- );
区别:
参数说明:
- HWND hCalc = FindWindow("Notepad", NULL);
- if (hCalc == NULL) {
- return FALSE;
- }
- PostMessage(hCalc,WM_QUIT,0,NULL);
-
- HWND hNotepad = FindWindow("Notepad", NULL);
- if (hNotepad == NULL) {
- return FALSE;
- }
- HWND hEdit = GetWindow(hNotepad, GW_CHILD);
- PostMessage(hEdit, WM_KEYDOWN, 'A', 0);
- PostMessage(hEdit, WM_KEYUP, 'B', 0);
- PostMessage(hEdit, WM_KEYDOWN, 'C', 0);
-
- HDC hdc = GetDC(hEdit);
- while (TRUE) {
- SetTextColor(hdc,RGB(255,0,0));
- TextOut(hdc, 0, 0, "SB", 2);
- }
- ReleaseDC(hEdit, hdc);

方式一:通过代码创建菜单,子菜单
- // 创建菜单资源
- HMENU HMenu = CreateMenu();
-
- // 给窗口添加菜单,向菜单中添加菜单项
- BOOL ret;
- ret = AppendMenu(HMenu, MF_STRING | MF_POPUP, (UINT_PTR)HMenu, _T("文件(&F)"));
- ret = AppendMenu(HMenu, MF_STRING | MF_POPUP, (UINT_PTR)HMenu, _T("编辑(&E)"));
-
- // 把菜单加载给窗口
- SetMenu(hWnd, HMenu);
-
- // 添加子菜单
- HMENU hSubMenu = GetSubMenu(HMenu, 0);
- ret = AppendMenu(hSubMenu, MF_STRING, IDM_OPEN, _T("打开(&O)"));
- ret = AppendMenu(hSubMenu, MF_STRING, IDM_SAVE, _T("保存(&O)"));
- ret = AppendMenu(hSubMenu, MF_STRING, IDM_EXIT, _T("退出(&O)"));
-
- // 把菜单加载给窗口
- SetMenu(hWnd, HMenu);
AppendMenu()函数:将新项追加到指定菜单栏、下拉菜单、子菜单或快捷菜单的末尾。 可以使用此函数指定菜单项的内容、外观和行为。
- BOOL AppendMenuA(
- [in] HMENU hMenu,
- [in] UINT uFlags,
- [in] UINT_PTR uIDNewItem,
- [in, optional] LPCSTR lpNewItem
- );
参数说明:
返回值:如果该函数成功,则返回值为非零值。 如果函数失败,则返回值为零。
SetMenu()函数:将新菜单分配给指定的窗口。
- BOOL SetMenu(
- [in] HWND hWnd,
- [in, optional] HMENU hMenu
- );
参数说明:
返回值:如果该函数成功,则返回值为非零值。如果函数失败,则返回值为零。
这种方式还需要手动声明宏定义
- #define IDM_OPEN 102
- #define IDM_SAVE 103
- #define IDM_EXIT 104
方式二:通过编辑菜单资源,给主窗口设计一个菜单,推荐使用
File菜单的属性中是没有ID的

下面的子菜单是有ID,可以通过快捷键 CTRL+O 打开

加载菜单
- HMENU hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1));
- SetMenu(hDlg, hMenu);
LoadMenu函数:获取菜单资源的句柄
- HMENU LoadMenuA(
- [in, optional] HINSTANCE hInstance,
- [in] LPCSTR lpMenuName
- );
参数说明:

子窗口Open的ID是:ID_OPEN;子窗口Save的ID是:ID_SAVE
这种方式下,系统会在.h文件给出对应的宏定义,我们不需要管
WM_COMMAND:当点击菜单的时候,会响系统发送一条WM_COMMAND消息。当消息处理函数接受到WM_COMMAND消息的时候处理菜单选项内容。
作用:用于处理菜单或快捷键 都会发送COMMAND消息,有窗口过程函数处理,该消息的参数:
处理WM_COMMAND消息实例
- switch (uMsg) {
- case WM_COMMAND:
- if (LOWORD(wParam) == ID_SAVE) {
-
- }
- else if (LOWORD(wParam) == IDB_LOGIN) {
-
- }
- break;
通过LOWOED()拿到wParam参数的低字,这里面信息就是ID值,前面定义的ID_SAVE,ID_OPEN
这样可以根据不同的菜单选择给出对应的处理方式。
图标资源

LoadIcon函数:获取图标资源的句柄
- HICON LoadIconA(
- [in, optional] HINSTANCE hInstance,
- [in] LPCSTR lpIconName
- );
参数说明:
如果 hInstance 为非 NULL, 则 lpIconName 按名称或序号指定图标资源。 必须使用 MAKEINTRESOURCE 宏打包此序号;如果 hInstance 为 NULL, 则 lpIconName 将指定标识符
代码如下:
- ws.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(MN_ICON));
- wc.hIcon = LoadIcon(NULL, IDI_HAND);
光标资源

LoadCursor:获取光标资源的句柄
- HCURSOR LoadCursorA(
- [in, optional] HINSTANCE hInstance,
- [in] LPCSTR lpCursorName
- );
参数说明:
返回值:如果函数成功,则返回值是新加载的游标的句柄。如果函数失败,则返回值为 NULL
代码如下:
- ws.hCursor = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_POINTER));
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
方式一:创建快捷键表

方式二:创建快捷键表
- // 申请堆控件,因为快捷键需要全局访问
- // 申请100字节的局部堆地址空间
- // 这样设计的原因,内存空间申请释放,产生了很多碎片,通过把这些碎片整理得到一个更大的内存空间,这是地址变化了
-
- // 申请局部堆地址
- HLOCAL hMenu = LocalAlloc(LHND,100);
- LPVOID lpMemory = LocalLock(hMenu);
- LocalFree(hMenu);
-
-
- // 申请全局堆地址
- // 原因:16位系统,有全局堆和局部堆;32位,两者合并,只有一个堆
- GlobalAlloc(LHND, 100);
-
-
- // 申请堆空间
- // 新的API,返回值是一个地址,前两个函数的底层是调用这个
- //HeapAlloc();
-
- // 申请堆地址空间,可以指定内存属性
- //VirtualAlloc();
-
- ACCEL *pAccelNews = (ACCEL*)HeapAlloc(GetProcessHeap(), 0, sizeof(ACCEL)*2);
-
- if (pAccelNews == nullptr) {
- ShowErrorMsg();
- return 0;
- }
-
- // 创建快捷键表
- HACCEL hAccel = CreateAcceleratorTable(pAccelNews, 2);
- if (hAccel == NULL) {
- ShowErrorMsg();
- return 0;
- }
-
- pAccelNews[0].fVirt = FALT | FCONTROL | FVIRTKEY;
- pAccelNews[0].key = 'A';
- pAccelNews[0].cmd = WM_COMMAND;
-
- pAccelNews[1].fVirt = FALT | FCONTROL | FVIRTKEY;
- pAccelNews[1].key = 'B';
- pAccelNews[1].cmd = WM_COMMAND;
加载快捷键:
LoadAccelerators():加载指定的快捷键表。
- HACCEL LoadAcceleratorsW(
- [in, optional] HINSTANCE hInstance,
- [in] LPCWSTR lpTableName
- );
参数说明:
返回值:如果函数成功,则返回值是加载的加速器表的句柄;如果函数失败,则返回值为 NULL。
TranslateAccelerator():把按键消息转换成WM_COMMAND消息,处理菜单命令的快捷键。 如果指定快捷键表中) 键有条目,函数会将WM_KEYDOWN或WM_SYSKEYDOWN ( 消息转换为WM_COMMAND或WM_SYSCOMMAND消息,然后将WM_COMMAND或WM_SYSCOMMAND消息直接发送到指定的窗口过程。 在窗口过程处理完消息之前,TranslateAccelerator 不会返回
- int TranslateAcceleratorA(
- [in] HWND hWnd,
- [in] HACCEL hAccTable,
- [in] LPMSG lpMsg
- );
参数说明:
返回值:如果该函数成功,则返回值为非零值;如果函数失败,则返回值为零。
代码如下:
- HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
-
- BOOL bRet;
- MSG msg;
- // 消息循环是以线程为单位的
- while ((bRet = GetMessage(&msg,NULL,0,0)) != 0) {
- if (bRet == -1) {
- break;
- }
- else {
- if (!TranslateAccelerator(hDlg, hAccel, &msg)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
- }
字符串资源:

LoadString():加载字符串资源
- int LoadStringA(
- [in, optional] HINSTANCE hInstance,
- [in] UINT uID,
- [out] LPSTR lpBuffer,
- [in] int cchBufferMax
- );
参数说明:
示例代码
- TCHAR szBuf[MAXBYTE];
- TCHAR szTitle[MAXWORD];
- LoadString(g_hInstance, IDS_SAVE, szBuf, sizeof(szBuf));
- LoadString(g_hInstance, IDS_Title, szTitle, sizeof(szTitle));
- MessageBox(hwndDlg, szBuf,szTitle, MB_OK);
总代码-1
- #include <windows.h>
- #include "resource.h"
-
- LRESULT CALLBACK MyWndProc(HWND, UINT, WPARAM, LPARAM);
-
- LRESULT OnMenu(HWND, UINT, WPARAM, LPARAM);
-
- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
- PSTR szCmdLine, int iCmdShow)
- {
- static char szAppName[] = "Hello Win";
-
- //设计窗口类
- WNDCLASS ws;
- ws.style = CS_HREDRAW | CS_VREDRAW;
- ws.lpfnWndProc = &MyWndProc;
- ws.cbClsExtra = NULL;
- ws.cbWndExtra = NULL;
- ws.hInstance = hInstance;
- ws.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(MN_ICON));
- ws.hCursor = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_POINTER));
- ws.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
- ws.lpszMenuName = NULL;//MAKEINTRESOURCE(MN_MAIN);
- ws.lpszClassName = szAppName;
-
- //注册窗口类
- if (!RegisterClass(&ws))
- {
- MessageBox(NULL, "注册窗口失败", "错误提示:", MB_OK);
- return 0;
- }
-
- //创建窗口
- HWND HelloHwnd = CreateWindow(
- szAppName,
- "The Hello Program",
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- NULL,
- LoadMenu(hInstance,MAKEINTRESOURCE(MN_MAIN)), //拿到资源的句柄
- hInstance,
- NULL,
- );
-
- //显示窗口
- ShowWindow(HelloHwnd, iCmdShow);
-
- //更新窗口,调用Begin使得画面有效
- UpdateWindow(HelloHwnd);
- SetTimer(HelloHwnd, 1, 100, NULL);
-
- //加载快捷键资源
- HACCEL haccel = LoadAccelerators(hInstance,MAKEINTRESOURCE(ACCEL_TEXT));
-
- //建立消息循环
- MSG msg;
- while (GetMessage(&msg, NULL, 0, 0))
- {
- if (!TranslateAccelerator(HelloHwnd,haccel,&msg))
- {
- TranslateMessage(&msg); //将msg结构传给Windows,进行一些键盘转换
- DispatchMessage(&msg); //使得自动调用消息窗口句柄所属的窗口过程函数
- }
- }
-
- return msg.wParam; //结构的wParam字段是传递给PostQuitMessage函数的值(通常是0)。然后return叙述将退出WinMain并终止程序。
- }
-
- //实现消息过程函数
- LRESULT CALLBACK MyWndProc(
- HWND hwnd, //
- UINT message, //
- WPARAM wParam, //参数wParam表明窗口是非最小化还是非最大化,是最小化、最大化,还是隐藏
- LPARAM lParam //lParam参数包含了新窗口的大小,新宽度和新高度均为16位值,合在一起成为32位的lParam。
- )
- {
- switch (message)
- {
- case WM_CREATE:
- return 0;
- case WM_COMMAND:
- return OnMenu(hwnd, message, wParam, lParam);
- case WM_DESTROY:
- PostQuitMessage(0); //发送WM_QUIT以结束消息循环
- return 0;
- }
-
- return DefWindowProc(hwnd, message, wParam, lParam); //操作系统待处理我们不处理的消息
- }
-
- //wParam 高位代表消息来源,地位代表ID
- LRESULT OnMenu(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- //判断是否来自于菜单
- if (HIWORD(wParam) == 0)
- {
- switch (LOWORD(wParam))
- {
- case MN_FILE_NEW:
- MessageBox(NULL, "MN_FILE_NEW", "菜单选项:", MB_OK);
- break;
- case MN_FILE_OPEN:
- MessageBox(NULL, "MN_FILE_OPEN", "菜单选项:", MB_OK);
- break;
- case MN_FILE_SAVE:
- MessageBox(NULL, "MN_FILE_SAVE", "菜单选项:", MB_OK);
- break;
- case MN_EDT_REDO:
- MessageBox(NULL, "MN_EDT_REDO", "菜单选项:", MB_OK);
- break;
- case MN_EDT_UNDO:
- MessageBox(NULL, "MN_EDT_UNDO", "菜单选项:", MB_OK);
- break;
- default:
- break;
- }
- }
- //
- else if (HIWORD(wParam) == 1)
- {
- switch (LOWORD(wParam))
- {
- case ACCEL_CTRL_A:
- MessageBox(NULL, "ACCEL_CTRL_A", "菜单选项:", MB_OK);
- break;
- case ACCEL_CTRL_ALT_A:
- MessageBox(NULL, "ACCEL_CTRL_ALT_A", "菜单选项:", MB_OK);
- break;
- default:
- break;
- }
- }
- return 0;
- }
总代码-2
- #include <windows.h>
- #include <tchar.h>
- #include <fstream>
- #include <string>
-
- #define IDM_OPEN 102
- #define IDM_SAVE 103
- #define IDM_EXIT 104
-
- using namespace std;
-
- string g_Text;
- TEXTMETRIC g_tm; // 字体信息
-
-
- void ShowErrorMsg() {
- LPVOID lpMsgBuf;
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR)&lpMsgBuf,
- 0,
- NULL
- );
- MessageBox(NULL, (LPCTSTR)lpMsgBuf, _T("ERROR"), MB_OK | MB_ICONINFORMATION);
- LocalFree(lpMsgBuf);
- }
-
-
- LRESULT OnCreate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- OutputDebugString(_T("[51asm]: WM_Create\n"));
-
- HDC hdc = GetDC(hwnd);
- SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
- GetTextMetrics(hdc, &g_tm);
- ReleaseDC(hwnd, hdc);
-
- return TRUE;
- }
-
-
- LRESULT OnClose(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- OutputDebugString(_T("[51asm]: WM_Close\n"));
- DestroyWindow(hwnd);
- return FALSE;
- }
-
-
- LRESULT OnDestroy(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- OutputDebugString(_T("[51asm]: WM_Destory\n"));
- PostMessage(hwnd, WM_QUIT, 0, NULL);
- return TRUE;
- }
-
-
-
- LRESULT OnChar(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- TCHAR szBuf[MAXBYTE];
-
- if ((char)wParam == '\r') {
- g_Text += (char)wParam;
- g_Text += '\n';
- }
- else if ((char)wParam == '\b') {
- if (!g_Text.empty()) {
- g_Text.pop_back();
- }
- }
- else {
- g_Text += (char)wParam;
- }
-
-
-
- wsprintf(szBuf, _T("[51asm] OnChar %s\n"), g_Text.data());
- OutputDebugString(szBuf);
-
- // // 获取窗口HDC,用API时一定要阅读文档
- // // 获取一个新的句柄时,往往是需要释放的,否则该进程的内存会越来愈大
- // //HDC hdc = GetWindowDC(hwnd); // 非客户区域
- //
- // HDC hdc = GetDC(hwnd);
- //
- // //TextOut(hdc, 0, 0, g_Text.data(), g_Text.length());
- // // 获取窗口客户区域大小
- // RECT rc;
- // GetClientRect(hwnd, &rc);
- //
- // // 创建一个白色的刷子
- // HGDIOBJ hBrushOld;
- // HBRUSH hBrush = CreateSolidBrush(RGB(255, 255, 255));
- // //check,可能会失败,需要GetLastError
- //
- //
- // // DC选择刷子
- // hBrushOld = SelectObject(hdc, hBrush);
- // //check
- //
- // // 绘制背景
- // FillRect(hdc, &rc, hBrush);
- // //check
- //
- // // 绘制文本
- // DrawText(hdc, g_Text.data(), g_Text.length(), &rc, DT_LEFT);
- // //check
- //
- // // 还原默认刷子
- // SelectObject(hdc, hBrushOld);
- // //check
- //
- // // 释放刷子
- // DeleteObject(hBrush);
- // //check
- //
- // // 释放DC
- // ReleaseDC(hwnd, hdc);
- // //check
- //
- // SetCaretPos(g_tm.tmAveCharWidth * g_Text.length(), 0);
- // ShowCaret(hwnd);
-
- // 采用方式2:
- RECT rc;
- GetClientRect(hwnd, &rc);
-
- // 把整个窗口设置为无效区域
- InvalidateRect(hwnd, NULL, TRUE);
-
- // 每当写入后就会产生WM_PAINT消息
-
- return TRUE;
- }
-
-
- LRESULT OnSetFocus(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- OutputDebugString(_T("[51asm] OnSetFocus\n"));
-
- CreateCaret(hwnd, (HBITMAP)NULL, 1, g_tm.tmHeight);
- SetCaretPos(0, 0);
- ShowCaret(hwnd);
-
- return TRUE;
- }
-
-
- LRESULT OnKillFocus(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- OutputDebugString(_T("[51asm] OnKillFocus\n"));
-
- DestroyCaret();
-
- return TRUE;
- }
-
-
- // 绘制
- LRESULT OnPaint(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- OutputDebugString(_T("[51asm] OnPaint\n"));
-
- // // 方式1
- // HDC hdc = GetDC(hwnd);
- //
- // // 获取窗口客户区域大小
- // RECT rc;
- // GetClientRect(hwnd, &rc);
- //
- // // 绘制文本
- // DrawText(hdc, g_Text.data(), g_Text.length(), &rc, DT_LEFT);
- // //check
- //
- // // 释放DC
- // ReleaseDC(hwnd, hdc);
- // //check
- //
- // // 将无效区域设置为有效区域
- // ValidateRect(hwnd,&rc);
-
-
-
-
- // 方式2:推荐
- PAINTSTRUCT ps;
- HDC hdc = BeginPaint(hwnd, &ps);
-
- RECT rc;
- GetClientRect(hwnd, &rc);
-
- DrawText(hdc, g_Text.data(), g_Text.length(), &rc, DT_LEFT);
-
- EndPaint(hwnd, &ps); // 自动把无效区域设置为有效区域
- return TRUE;
-
-
- // 无效区域,有变化的区域,系统需要重新绘制,WM_PAINT来了
- // 有效区域,不需要变化,系统不需要冲洗绘制
- // 设置无效区域为有效区域属于GDI的API
-
- return TRUE;
- }
-
-
- // 擦除背景
- LRESULT OnEraseBackground(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- OutputDebugString(_T("[51asm] OnEraseBackground\n"));
-
- DestroyCaret();
-
- return TRUE;
- }
-
-
- LRESULT OnCommand(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- OutputDebugString(_T("[51asm] OnCommand\n"));
- WORD wID = LOWORD(wParam);
- switch (wID) {
- case IDM_OPEN:
- MessageBox(NULL, "打开", "51asm", MB_OK);
- break;
- case IDM_EXIT:
- PostQuitMessage(0); // 给自己投递QUIT消息
- break;
- }
- return TRUE;
- }
-
-
-
-
-
- // 消息处理
- // 可以下断点debug调试分析消息,在监视这里可以 uMsg.wm 可以以看到
- // 先创建非客户区,再创建客户区,还有创建窗口等很多消息
- LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- LRESULT lResult = FALSE;
-
- switch (uMsg) {
- case WM_CREATE:
- lResult = OnCreate(hwnd, uMsg, wParam, lParam);
- break;
- case WM_CLOSE:
- lResult = OnClose(hwnd, uMsg, wParam, lParam);
- break;
- case WM_DESTROY:
- lResult = OnDestroy(hwnd, uMsg, wParam, lParam);
- break;
- case WM_CHAR:
- lResult = OnChar(hwnd, uMsg, wParam, lParam);
- break;
- case WM_SETFOCUS:
- lResult = OnSetFocus(hwnd, uMsg, wParam, lParam);
- break;
- case WM_KILLFOCUS:
- lResult = OnKillFocus(hwnd, uMsg, wParam, lParam);
- break;
- case WM_ERASEBKGND: // 刷背景,最大化时候会刷背景,最小化不会刷
- lResult = OnEraseBackground(hwnd, uMsg, wParam, lParam);
- break;
- case WM_PAINT: //绘制消息,窗口(界面)发生变化就会产生这个消息
- lResult = OnPaint(hwnd, uMsg, wParam, lParam);
- break;
- case WM_COMMAND: //绘制消息,窗口(界面)发生变化就会产生这个消息
- lResult = OnCommand(hwnd, uMsg, wParam, lParam);
- break;
- }
-
- if (!lResult) {
- return DefWindowProc(hwnd, uMsg, wParam, lParam); // 默认窗口过程处理函数,包括销毁窗口
- }
- return lResult;
- }
-
-
-
- int WINAPI wWinMain(
- HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPWSTR lpCmdLine,
- int nShowCmd
- ) {
- // 骚操作,在本窗口给别的窗口发消息
- // 启动一个记事本,发送退出消息
- // HWND hCalc = FindWindow("Notepad", NULL);
- // if (hCalc == NULL) {
- // return FALSE;
- // }
- // // 需要让GetMassage()拿到这个消息
- // //SendMessage(hCalc,WM_QUIT,0,NULL); 调用对方过程函数,消息没进消息队列,处理不到
- // //PostMessage();
- // PostMessage(hCalc,WM_QUIT,0,NULL);
-
- // HWND hNotepad = FindWindow("Notepad", NULL);
- // if (hNotepad == NULL) {
- // return FALSE;
- // }
- // HWND hEdit = GetWindow(hNotepad, GW_CHILD);
- // PostMessage(hEdit, WM_KEYDOWN, 'A', 0);
- // PostMessage(hEdit, WM_KEYUP, 'B', 0);
- // PostMessage(hEdit, WM_KEYDOWN, 'C', 0);
- //
- // HDC hdc = GetDC(hEdit);
- // while (TRUE) {
- // SetTextColor(hdc,RGB(255,0,0));
- // TextOut(hdc, 0, 0, "SB", 2);
- // }
- // ReleaseDC(hEdit, hdc);
-
-
-
- // 创建窗口实例
- TCHAR szWndClassName[] = { _T("CR41WndClassName") };
-
- WNDCLASSEX wc = { 0 };
- wc.cbSize = sizeof(WNDCLASSEX);
- wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
- wc.lpfnWndProc = WindowProc;
- wc.hInstance = hInstance;
- wc.hIcon = LoadIcon(NULL, IDI_HAND);
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = CreateSolidBrush(RGB(255, 255, 255));
- wc.lpszMenuName = NULL;
- wc.lpszClassName = szWndClassName;
-
- // 注册窗口
- if (RegisterClassEx(&wc) == 0) {
- ShowErrorMsg();
- return 0;
- }
-
-
- // 创建窗口
- TCHAR szWndName[] = { _T("51asm") };
- HWND hWnd = CreateWindowEx(0,
- szWndClassName,
- szWndName,
- WS_OVERLAPPEDWINDOW, //组合属性,可拉伸窗口
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- NULL,
- NULL,
- hInstance,
- NULL);
-
-
-
- if (hWnd == NULL) {
- ShowErrorMsg();
- return 0;
- }
-
- // 菜单
- HMENU hMenu = CreateMenu();
-
- // 弹出菜单
- BOOL ret;
- ret = AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT_PTR)hMenu, "文件(&F)");
- ret = AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT_PTR)hMenu, "编辑(&E)");
- SetMenu(hWnd, hMenu);
-
- // 添加子菜单
- HMENU hSubMenu = GetSubMenu(hMenu, 0);
- ret = AppendMenu(hSubMenu, MF_STRING, IDM_OPEN, "打开(&O)");
- ret = AppendMenu(hSubMenu, MF_STRING, IDM_SAVE, "保存(&O)");
- ret = AppendMenu(hSubMenu, MF_STRING, IDM_EXIT, "退出(&O)");
-
- SetMenu(hWnd, hMenu);
-
-
- RECT rc;
- GetClientRect(hWnd, &rc);
-
- // 控件:带有特殊功能的窗口
- // 按钮 编辑框
- // HWND hEdit = CreateWindowEx(0,
- // _T("Edit"),
- // NULL,
- // WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE, //组合属性,可拉伸窗口 最后一个表示支持多行
- // 0,
- // 0,
- // rc.right - rc.left,
- // rc.bottom - rc.top,
- // hWnd,
- // NULL,
- // hInstance,
- // NULL);
-
-
-
- // 显示,更新窗口
- ShowWindow(hWnd, SW_SHOWNORMAL); // 调用Show时候父子窗口都会被调用
- //ShowWindow(hChild, SW_SHOWNORMAL); 非子窗口需要单独show
- UpdateWindow(hWnd); // 产生WM_PAINT
-
- SetClassLong(hWnd, GCL_HCURSOR, (LONG)LoadCursor(NULL, IDC_CROSS));
-
-
-
-
- // 消息循环
- BOOL bRet;
- MSG msg;
- while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
- {
- if (bRet == -1) {
- break;
- }
- else {
- TranslateMessage(&msg);// 转换键盘消息
- DispatchMessage(&msg); // 派发消息
- }
- }
-
-
- return msg.wParam;
- }
总代码-3:
- #include <windows.h>
- #include <tchar.h>
- #include <fstream>
- #include <string>
-
- #define IDM_OPEN 102
- #define IDM_SAVE 103
- #define IDM_EXIT 104
-
- using namespace std;
-
- string g_Text;
- TEXTMETRIC g_tm; // 字体信息
-
-
- void ShowErrorMsg() {
- LPVOID lpMsgBuf;
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR)&lpMsgBuf,
- 0,
- NULL
- );
- MessageBox(NULL, (LPCTSTR)lpMsgBuf, _T("ERROR"), MB_OK | MB_ICONINFORMATION);
- LocalFree(lpMsgBuf);
- }
-
-
- LRESULT OnCreate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- OutputDebugString(_T("[51asm]: WM_Create\n"));
- return TRUE;
- }
-
- // 当你关闭窗口点击确定后就会向窗口发送WM_Destroy消息,就意味要销毁窗口,
- LRESULT OnClose(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- OutputDebugString(_T("[51asm]: WM_Close\n"));
- return FALSE;
- }
-
- // 这个工作可以交给系统处理,也可以自己处理
- LRESULT OnDestroy(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- OutputDebugString(_T("[51asm]: WM_Destory\n"));
- return TRUE;
- }
-
-
-
- LRESULT OnCommand(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- OutputDebugString(_T("[51asm] OnCommand\n"));
- WORD wID = LOWORD(wParam);
- switch (wID) {
- case IDM_OPEN:
- MessageBox(NULL, _T("打开"), _T("51asm"), MB_OK);
- break;
- case IDM_EXIT:
- PostQuitMessage(0); // 给自己投递QUIT消息
- break;
- }
- return TRUE;
- }
-
-
-
- LRESULT OnKeyDown(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- OutputDebugString(_T("[51asm]: OnKeyDown\n"));
- return TRUE;
- }
-
-
-
- LRESULT OnKeyUp(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- OutputDebugString(_T("[51asm]: OnKeyUp\n"));
- return TRUE;
- }
-
-
-
- // 消息处理
- // 可以下断点debug调试分析消息,在监视这里可以 uMsg.wm 可以以看到
- // 先创建非客户区,再创建客户区,还有创建窗口等很多消息
- LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- LRESULT lResult = FALSE;
-
- switch (uMsg) {
- case WM_CREATE:
- lResult = OnCreate(hwnd, uMsg, wParam, lParam); // 表示处理WM_CREATE消息的函数
- break;
- case WM_CLOSE:
- lResult = OnClose(hwnd, uMsg, wParam, lParam);
- break;
- case WM_DESTROY:
- lResult = OnDestroy(hwnd, uMsg, wParam, lParam);
- break;
- case WM_COMMAND: //绘制消息,窗口(界面)发生变化就会产生这个消息
- lResult = OnCommand(hwnd, uMsg, wParam, lParam);
- break;
- case WM_KEYDOWN: //绘制消息,窗口(界面)发生变化就会产生这个消息
- lResult = OnKeyDown(hwnd, uMsg, wParam, lParam);
- break;
- case WM_KEYUP: //绘制消息,窗口(界面)发生变化就会产生这个消息
- lResult = OnKeyUp(hwnd, uMsg, wParam, lParam);
- break;
- }
-
- if (!lResult) {
- return DefWindowProc(hwnd, uMsg, wParam, lParam); // 默认窗口过程处理函数,包括销毁窗口
- }
- return lResult;
- }
-
- /*
- 客户区(用户区)与非客户区(系统的) NC
-
-
- */
-
- int WINAPI wWinMain(
- HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPWSTR lpCmdLine,
- int nShowCmd
- ) {
- // 申请堆控件,因为快捷键需要全局访问
- // 申请100字节的局部堆地址空间
- // 这样设计的原因,内存空间申请释放,产生了很多碎片,通过把这些碎片整理得到一个更大的内存空间,这是地址变化了
-
- // 申请局部堆地址
- HLOCAL hMenu = LocalAlloc(LHND,100);
- LPVOID lpMemory = LocalLock(hMenu);
- LocalFree(hMenu);
-
-
- // 申请全局堆地址
- // 原因:16位系统,有全局堆和局部堆;32位,两者合并,只有一个堆
- GlobalAlloc(LHND, 100);
-
-
- // 申请堆空间
- // 新的API,返回值是一个地址,前两个函数的底层是调用这个
- //HeapAlloc();
-
- // 申请堆地址空间,可以指定内存属性
- //VirtualAlloc();
-
- ACCEL *pAccelNews = (ACCEL*)HeapAlloc(GetProcessHeap(), 0, sizeof(ACCEL)*2);
-
- if (pAccelNews == nullptr) {
- ShowErrorMsg();
- return 0;
- }
-
- // 创建快捷键表
- HACCEL hAccel = CreateAcceleratorTable(pAccelNews, 2);
- if (hAccel == NULL) {
- ShowErrorMsg();
- return 0;
- }
-
- pAccelNews[0].fVirt = FALT | FCONTROL | FVIRTKEY;
- pAccelNews[0].key = 'A';
- pAccelNews[0].cmd = WM_COMMAND;
-
- pAccelNews[1].fVirt = FALT | FCONTROL | FVIRTKEY;
- pAccelNews[1].key = 'B';
- pAccelNews[1].cmd = WM_COMMAND;
-
-
-
-
-
- // 创建窗口实例
- TCHAR szWndClassName[] = { _T("CR41WndClassName") };
-
- WNDCLASSEX wc = { 0 };
- wc.cbSize = sizeof(WNDCLASSEX);
- wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
- wc.lpfnWndProc = WindowProc;
- wc.hInstance = hInstance;
- wc.hIcon = LoadIcon(NULL, IDI_HAND);
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = CreateSolidBrush(RGB(255, 255, 255));
- wc.lpszMenuName = NULL;
- wc.lpszClassName = szWndClassName;
-
- // 注册窗口
- if (RegisterClassEx(&wc) == 0) {
- ShowErrorMsg();
- return 0;
- }
-
-
- // 创建窗口
- TCHAR szWndName[] = { _T("51asm") };
- HWND hWnd = CreateWindowEx(0,
- szWndClassName,
- szWndName,
- WS_OVERLAPPEDWINDOW, //组合属性,可拉伸窗口
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- NULL,
- NULL,
- hInstance,
- NULL);
-
-
-
- if (hWnd == NULL) {
- ShowErrorMsg();
- return 0;
- }
-
- // 菜单
- HMENU HMenu = CreateMenu();
-
- // 弹出菜单
- BOOL ret;
- ret = AppendMenu(HMenu, MF_STRING | MF_POPUP, (UINT_PTR)HMenu, _T("文件(&F)"));
- ret = AppendMenu(HMenu, MF_STRING | MF_POPUP, (UINT_PTR)HMenu, _T("编辑(&E)"));
- SetMenu(hWnd, HMenu);
-
- // 添加子菜单
- HMENU hSubMenu = GetSubMenu(HMenu, 0);
- ret = AppendMenu(hSubMenu, MF_STRING, IDM_OPEN, _T("打开(&O)"));
- ret = AppendMenu(hSubMenu, MF_STRING, IDM_SAVE, _T("保存(&O)"));
- ret = AppendMenu(hSubMenu, MF_STRING, IDM_EXIT, _T("退出(&O)"));
-
- SetMenu(hWnd, HMenu);
-
-
- // RECT rc;
- // GetClientRect(hWnd, &rc);
-
-
- // 显示,更新窗口
- ShowWindow(hWnd, SW_SHOWNORMAL); // 调用Show时候父子窗口都会被调用
- //ShowWindow(hChild, SW_SHOWNORMAL); 非子窗口需要单独show
- UpdateWindow(hWnd); // 产生WM_PAINT
-
- SetClassLong(hWnd, GCL_HCURSOR, (LONG)LoadCursor(NULL, IDC_CROSS));
-
-
-
-
- // 消息循环
- BOOL bRet;
- MSG msg;
- while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
- {
- if (bRet == -1) {
- break;
- }
- else {
- // 转换快捷键消息 WM_COMMAND
- if (!TranslateAccelerator(hWnd, hAccel, &msg)) {
- TranslateMessage(&msg);// 转换键盘消息
- DispatchMessage(&msg); // 派发消息
- }
- }
- }
-
- // 删除快捷键表
- DestroyAcceleratorTable(hAccel);
- HeapFree(GetProcessHeap(), 0, pAccelNews);
-
- return msg.wParam;
- }