本文为笔者踩过的Win32 Api坑以及解决办法,在此分享,避免大家踩坑。本文将持续更新。
注:坑度3星及以下为常规坑,3星以上为必填坑
目录
7、InitInstance函数与WM_CREATE执行顺序
1、OPENFILENAME
坑:若OPENFILENAME的成员变量Flags不设置OFN_NOCHANGEDIR, 使用GetOpenFileName函数后会导致相对路径发生改变。
坑度:★★★★☆
解决办法:在flags中设置OFN_NOCHANGEDIR,确保相对路径保持不变。
2、WinSock2.h与Windows.h
坑:若Windows.h放在WinSock2.h前面会导致大量重定义报错,造成编译失败。
坑度:★★★☆☆
解决办法:把WinSock2.h放在Windows.h前面或在开头添加WIN32_LEAN_AND_MEAN宏定义。
3、htons
坑:htons报error C4996
坑度:★☆☆☆☆
解决办法:#define _WINSOCK_DEPRECATED_NO_WARNINGS。
4、系统兼容性问题
坑:WIN10+VS2019生成的exe无法在WIN7上运行
坑度:★★★★☆
解决办法:
(1)下载Microsoft Visual C++ Redistributable for Visual Studio 2019(https://visualstudio.microsoft.com/zh-hans/downloads/)
(2)用Release模式,然后预编译宏_WIN32_WINNT=0x601(WIN7对应6.01)
5、SHDefExtractIconA获取图标ID问题
坑度:★★★☆☆
解决办法:
若要使用此函数需要以下头文件和库
#include <ShlObj_core.h>
#pragma comment(lib,"shell32.lib")
第二个参数正值为资源的顺序排列序号,负值为内部资源ID号,若已知资源ID为1004则第二参数填-1004即可
最后一个参数为提取图标的尺寸大小(之所以用这个函数就是能够指定图标的尺寸,其他函数得到的图标一般都是32x32)
本函数需要与DrawIconEx配合才能绘制正确尺寸的图标
6、图标显示不正确问题
坑度:★★★☆☆
(1)标题栏图标与任务栏图标只需要在WNDCLASSEXW结构体中定义即
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));//加载资源中的图标
HICON ico=ExtractIconA(hInstance, "icon路径", 0);//直接从外部加载
注意是用hInstance不是hinst,因为此时hinst还未被赋值
(2)exe图标
必须先把图标加入到资源中,图标ID号只要不跟其他ID重复即可
注意是用hInstance不是hinst,因为此时hinst还未被赋值
7、InitInstance函数与WM_CREATE执行顺序
坑度:★★☆☆☆
经过实测,InitInstance会先执行在其内部的CreateWindowW函数执行完后会跳到WM_CREATE中继续执行,执行完后跳到CreateWindowW下一行继续执行InitInstance中的其他语句,有关窗体的全局变量应放在WM_CREATE里初始化,ShowWindow执行后就显示窗口了
8、动态修改菜单
坑度:★★☆☆☆
(1)修改文字
HMENU hm = GetMenu(hWnd);//获取窗口菜单根节点
hm = GetSubMenu(hm, 0);//获取第一个子菜单列
//GetMenuItemID(hm, 1);测试时使用,按序列位置查找hm中的第2个菜单,看返回的ID号和定义的是否相同
ModifyMenuA(hm, 1, MF_BYPOSITION | MF_STRING, ID_32777, "继续");//按序列位置查找|只修改文字
CheckMenuItem(hm, 2, MF_UNCHECKED | MF_BYPOSITION);//设置不打勾|按序列位置查找
9、颜色拾取对话框
坑度:★★☆☆☆
COLORREF bgcolor{0};
COLORREF cuscolor[16]{ 0 };//必须要给一个颜色数组否则报错
CHOOSECOLORA pc{0};
pc.hwndOwner = hWnd;
pc.lStructSize = sizeof(CHOOSECOLORA);
pc.rgbResult = bgcolor;
pc.lpCustColors = cuscolor;
pc.Flags = CC_ANYCOLOR |CC_RGBINIT| CC_FULLOPEN;
if (ChooseColorA(&pc) == FALSE)
{
MessageBoxA(hWnd, "颜色拾取失败", "", 0);
break;
}
bgcolor = pc.rgbResult;
10、Dialog中使用Messagebox无法关闭
坑度:★★★★☆
在DlgProc中的消息处理中
设置default:return 0;
即可正常关闭Messagebox
11、Combo Box下拉框过短问题
坑度:★★★★☆
选中Combo Box控件后把鼠标移到右边的下箭头上,鼠标变成上下箭头,向下拖动足够宽度即可。
12、Dialog中的子控件的消息处理
坑度:★★★★☆
Dialog中的子控件消息都是通过DialogProc中的WM_COMMAND中处理。
先switch(LOWORD(wParam))获得Dialog中的消息
再case 子控件的ID
在内部再switch(HIWORD(wParam))获得控件消息
最后case 子控件的消息(例如CBN_SELCHANGE)
PS:要获得控件内部属性用SendMessage(),2参为控件操作信息
13、模态与非模态对话框
坑度:★★★☆☆
非模态对话框用CreateDialog创建,DestroyWindow销毁。
模态对话框用DialogBox创建,EndDialog销毁。
14、禁止子窗口自动重绘
坑度:★★★☆☆
解决方法:在父窗口类定义时加入WS_CLIPCHILDREN告诉系统父窗口绘制时裁掉子窗口区域从而避免子窗口重绘。
PS:只是在子窗口中的WM_PAINT事件中用空语句也不能阻止子窗口重绘
15、TransparentBlt()不显示返回FALSE
坑度:★★★★☆
如果前面的hdcm有更改过SetMapMode()、SetViewportOrgEx()均会导致错误
如果TransparentBlt()中倒数2、3参数大于hdcm中bmp的尺寸也会导致错误
PS:错误代码87