Win32 Api 填坑之旅

本文为笔者踩过的Win32 Api坑以及解决办法,在此分享,避免大家踩坑。本文将持续更新。

注:坑度3星及以下为常规坑,3星以上为必填坑

目录

1、OPENFILENAME

2、WinSock2.h与Windows.h

3、htons

4、系统兼容性问题

5、SHDefExtractIconA获取图标ID问题

6、图标显示不正确问题

7、InitInstance函数与WM_CREATE执行顺序

8、动态修改菜单

9、颜色拾取对话框

10、Dialog中使用Messagebox无法关闭

11、Combo Box下拉框过短问题

12、Dialog中的子控件的消息处理

13、模态与非模态对话框

14、禁止子窗口自动重绘


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值