去除Win32 Tab Control控件每个选项卡上的深色对话框背景

news/2024/7/23 21:09:15 标签: win32, tab, 背景, brush, visual studio

一般情况下,我们是用不带边框的对话框来充当Tab Control的每个选项卡的内容的。
例如,主对话框IDD_TABBOX上有一个Tab Control,上面有两个选项卡,第一个选项卡用的是IDD_DIALOG1充当内容,第二个用的则是IDD_DIALOG2。IDD_DIALOG1和IDD_DIALOG2的Border属性设为None,Style属性设为Child,如下三张图所示。

但是用对话框充当选项卡内容会有烦人的深色对话框背景,和选项卡的样式并不搭,看起来也不好看,如下图所示。

其实,要去掉这个深色对话框背景很简单,只需要在每个选项卡的对话框的消息处理函数的WM_INITDIALOG里面加一句EnableThemeDialogTexture(hdlg, ETDT_ENABLETAB);就行了。有多少个选项卡,就加多少句这句话。
使用EnableThemeDialogTexture函数前,需要包含头文件Uxtheme.h和库文件Uxtheme.lib。该函数支持Windows XP系统。
#include <Uxtheme.h>
#pragma comment(lib, "Uxtheme.lib")

注意:使用这个函数后,如果程序处理了Static控件的WM_CTLCOLORSTATIC消息,直接return 0就可以用渐变背景了。不需要返回HBRUSH背景刷,SetTextColor设置的文字颜色就能生效。

 运行之后是这样的:

深色的对话框背景就成功去除掉了。话说XP系统的选项卡界面真的挺好看的,是一个渐变色。

【完整C语言代码】

main.c:

/* 参考资料:https://stackoverflow.com/questions/43768291/how-to-get-correct-background-and-control-colors-in-property-pages */
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <WindowsX.h>
#include <CommCtrl.h>
#include <Uxtheme.h>
#include "resource.h"

#pragma comment(lib, "comctl32.lib")
#pragma comment(linker, "\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' language='*' publicKeyToken='6595b64144ccf1df'\"")
#pragma comment(lib, "Uxtheme.lib")

#define COLOR_BLUE   RGB(0, 0, 255)
#define COLOR_RED    RGB(255, 0, 0)
#define COLOR_ORANGE RGB(255, 201, 14)
#define COLOR_GREEN  RGB(0, 255, 0)

COLORREF msg_color = COLOR_RED;
HFONT big_font;
HINSTANCE main_instance;
HWND main_dlg;

/* 获取指定选项卡的对话框窗口 */
HWND get_tab_page(int index)
{
	HWND tabctrl;
	TCITEM item;

	tabctrl = GetDlgItem(main_dlg, IDC_TAB1);
	item.mask = TCIF_PARAM;
	TabCtrl_GetItem(tabctrl, index, &item);
	return (HWND)item.lParam;
}

/* 修改文本内容和颜色 */
void change_static2_text(const char *str, COLORREF color)
{
	HWND page;

	page = get_tab_page(0);
	msg_color = color;
	SetDlgItemTextA(page, IDC_STATIC2, str);
}

/* 在下拉菜单框中显示串口列表 */
int display_comm_ports(HWND combobox)
{
	char name[50];
	char value[50];
	DWORD index, type, namelen, valuelen;
	HKEY key;
	LSTATUS status;

	ComboBox_ResetContent(combobox);
	status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_READ, &key);
	if (status != ERROR_SUCCESS)
		return -1;

	index = 0;
	while (1)
	{
		namelen = sizeof(name);
		valuelen = sizeof(value);
		status = RegEnumValueA(key, index, name, &namelen, NULL, &type, (LPBYTE)value, &valuelen);
		if (status != ERROR_SUCCESS)
			break;
		SendMessageA(combobox, CB_ADDSTRING, 0, (LPARAM)value);
		index++;
	}
	if (index != 0)
		ComboBox_SetCurSel(combobox, 0);

	RegCloseKey(key);
	return 0;
}

/* 选项卡1消息响应函数 */
INT_PTR CALLBACK page1_proc(HWND hdlg, UINT umsg, WPARAM wparam, LPARAM lparam)
{
	int id;

	switch (umsg)
	{
	case WM_COMMAND:
		id = LOWORD(wparam);
		switch (id)
		{
		case IDOK:
			// 点击“连接”按钮后执行的代码
			EnableWindow((HWND)lparam, FALSE);
			SetWindowTextA((HWND)lparam, "已连接");
			EnableWindow(GetDlgItem(hdlg, IDC_COMBO1), FALSE);
			EnableWindow(GetDlgItem(hdlg, IDC_RADIO1), FALSE);
			EnableWindow(GetDlgItem(hdlg, IDC_RADIO2), FALSE);
			change_static2_text("连接成功", COLOR_GREEN);
			break;
		case IDC_CHECK1:
			if (Button_GetCheck((HWND)lparam))
				EnableWindow(GetDlgItem(hdlg, IDC_EDIT1), TRUE);
			else
				EnableWindow(GetDlgItem(hdlg, IDC_EDIT1), FALSE);
			break;
		case IDC_CHECK2:
			if (Button_GetCheck((HWND)lparam))
			{
				EnableWindow(GetDlgItem(hdlg, IDC_EDIT2), TRUE);
				EnableWindow(GetDlgItem(hdlg, IDC_SPIN1), TRUE);
			}
			else
			{
				EnableWindow(GetDlgItem(hdlg, IDC_EDIT2), FALSE);
				EnableWindow(GetDlgItem(hdlg, IDC_SPIN1), FALSE);
			}
			break;
		}
		break;
	case WM_CTLCOLORSTATIC:
		// 设置文本颜色
		id = GetDlgCtrlID((HWND)lparam);
		if (id == IDC_STATIC2)
			SetTextColor((HDC)wparam, msg_color);
		break;
	case WM_INITDIALOG:
		EnableThemeDialogTexture(hdlg, ETDT_ENABLETAB); // 删除选项卡灰色背景

		display_comm_ports(GetDlgItem(hdlg, IDC_COMBO1)); // 在下拉菜单框中显示串口列表
		Button_SetCheck(GetDlgItem(hdlg, IDC_RADIO1), BST_CHECKED); // 选中第一个单选框
		SendDlgItemMessage(hdlg, IDC_STATIC2, WM_SETFONT, (WPARAM)big_font, TRUE); // 设置文本字体

		SendDlgItemMessage(hdlg, IDC_SPIN1, UDM_SETRANGE, 0, MAKELPARAM(100, 0)); // 设置数值上下调整框的调整范围
		SendDlgItemMessage(hdlg, IDC_SPIN1, UDM_SETPOS, 0, 25); // 设置数值上下调整框的当前值为25 (倒数第二个参数没有作用, 一般设置为0)
		break;
	}
	return 0;
}

/* 选项卡2消息响应函数 */
INT_PTR CALLBACK page2_proc(HWND hdlg, UINT umsg, WPARAM wparam, LPARAM lparam)
{
	char name[50];
	int i;
	HICON icon;
	HIMAGELIST imglist;
	HWND list_wnd;
	LVITEMA lvi;

	switch (umsg)
	{
	case WM_INITDIALOG:
		EnableThemeDialogTexture(hdlg, ETDT_ENABLETAB); // 删除选项卡灰色背景

		list_wnd = GetDlgItem(hdlg, IDC_LIST1);
		ListView_SetExtendedListViewStyle(list_wnd, LVS_EX_DOUBLEBUFFER); // 使用蓝色半透明选择框
		
		// 创建图像列表
		imglist = ImageList_Create(32, 32, ILC_COLOR24, 1, 1);
		ListView_SetImageList(list_wnd, imglist, LVSIL_NORMAL); // 绑定图像列表(绑定后,关闭窗口时会自动删除图像列表)
		icon = LoadImage(main_instance, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR); // 加载图标
		ImageList_AddIcon(imglist, icon); // 将图标复制到图像列表中(注意是复制,不是绑定)
		DestroyIcon(icon); // 复制完后要删除刚才加载的图标

		// 添加显示项目
		for (i = 0; i < 50; i++)
		{
			lvi.mask = LVIF_IMAGE | LVIF_TEXT;
			lvi.iItem = i; // 行号
			lvi.iSubItem = 0; // 列号
			_snprintf_s(name, sizeof(name), sizeof(name) - 1, "测试项目%02d", i + 1); // 第三个参数MaxCount是字符数,不包括'\0',所以必须减1
			lvi.pszText = name; // 名称
			lvi.iImage = 0; // 使用的图标序号
			lvi.iItem = (int)SendMessage(list_wnd, LVM_INSERTITEMA, 0, (LPARAM)&lvi); // 返回值为排序后的行号 (若启用了自动排序功能的话)
		}
		break;
	}
	return 0;
}

/* 加载字体 */
void create_font()
{
	LOGFONTA font = {0};

	font.lfCharSet = DEFAULT_CHARSET;
	strcpy_s(font.lfFaceName, sizeof(font.lfFaceName), "Times New Roman");
	font.lfHeight = 24;
	font.lfWeight = FW_BOLD;
	big_font = CreateFontIndirectA(&font);
}

/* 删除字体 */
void delete_font()
{
	DeleteObject(big_font);
}

/* 初始化选项卡控件 */
void init_tabs()
{
	char *titles[2] = {"第一个选项卡", "第二个选项卡"};
	int pages[2] = {IDD_DIALOG1, IDD_DIALOG2};
	DLGPROC procs[2] = {page1_proc, page2_proc};

	int i;
	HWND tabctrl, page;
	RECT rect;
	TCITEMA item;
	UINT flags;
	
	tabctrl = GetDlgItem(main_dlg, IDC_TAB1);
	for (i = 0; i < _countof(pages); i++)
	{
		item.mask = TCIF_TEXT;
		item.pszText = titles[i];
		SendMessage(tabctrl, TCM_INSERTITEMA, i, (LPARAM)&item);
	}

	GetClientRect(tabctrl, &rect);
	TabCtrl_AdjustRect(tabctrl, FALSE, &rect);
	for (i = 0; i < _countof(pages); i++)
	{
		page = CreateDialog(main_instance, MAKEINTRESOURCE(pages[i]), tabctrl, procs[i]);
		flags = (i == 0) ? SWP_SHOWWINDOW : 0;
		SetWindowPos(page, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, flags);

		item.mask = TCIF_PARAM;
		item.lParam = (LPARAM)page;
		TabCtrl_SetItem(tabctrl, i, &item);
	}
}

/* 切换选项卡 */
void switch_tab()
{
	int i, n, curr;
	HWND tabctrl;
	TCITEM item;
	
	tabctrl = GetDlgItem(main_dlg, IDC_TAB1);
	n = TabCtrl_GetItemCount(tabctrl);
	curr = TabCtrl_GetCurSel(tabctrl);
	for (i = 0; i < n; i++)
	{
		item.mask = TCIF_PARAM;
		TabCtrl_GetItem(tabctrl, i, &item);
		if (i == curr)
			ShowWindow((HWND)item.lParam, SW_SHOW);
		else
			ShowWindow((HWND)item.lParam, SW_HIDE);
	}
}

/* 主对话框(仅包含选项卡控件)消息响应函数 */
INT_PTR CALLBACK tabbox_proc(HWND hdlg, UINT umsg, WPARAM wparam, LPARAM lparam)
{
	int id;
	LPNMHDR lpnmhdr;

	switch (umsg)
	{
	case WM_COMMAND:
		id = LOWORD(wparam);
		switch (id)
		{
		case IDCANCEL:
			EndDialog(hdlg, 0);
			main_dlg = NULL;
			delete_font();
			break;
		}
		break;
	case WM_INITDIALOG:
		main_dlg = hdlg;
		lparam = (LPARAM)LoadImage(main_instance, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
		SendMessage(hdlg, WM_SETICON, ICON_BIG, lparam);
		lparam = (LPARAM)LoadImage(main_instance, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
		SendMessage(hdlg, WM_SETICON, ICON_SMALL, lparam);

		create_font();
		init_tabs();
		break;
	case WM_NOTIFY:
		lpnmhdr = (LPNMHDR)lparam;
		switch (lpnmhdr->code)
		{
		case TCN_SELCHANGE:
			switch_tab();
			break;
		}
		break;
	}
	return 0;
}

/* 主函数 */
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	LRESULT ret;

	main_instance = hInstance;
	InitCommonControls();

	ret = DialogBox(hInstance, MAKEINTRESOURCE(IDD_TABBOX), NULL, tabbox_proc);
	return (int)ret;
}

resource.h:

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by remove_tab_page_background.rc
//
#define IDI_ICON1                       101
#define IDD_DIALOG1                     102
#define IDD_DIALOG2                     103
#define IDD_TABBOX                      104
#define IDC_COMBO1                      1001
#define IDC_RADIO1                      1002
#define IDC_RADIO2                      1003
#define IDC_STATIC2                     1004
#define IDC_CHECK1                      1005
#define IDC_EDIT1                       1006
#define IDC_CHECK2                      1007
#define IDC_EDIT2                       1008
#define IDC_SPIN1                       1009
#define IDC_LIST1                       1010
#define IDC_TAB1                        1011

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        105
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1012
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

remove_tab_page_background.rc:

// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/
#undef APSTUDIO_READONLY_SYMBOLS

/
// 中文(简体,中国) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED

#ifdef APSTUDIO_INVOKED
/
//
// TEXTINCLUDE
//

1 TEXTINCLUDE 
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE 
BEGIN
    "#include ""afxres.h""\r\n"
    "\0"
END

3 TEXTINCLUDE 
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED


/
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1               ICON                    "icon1.ico"

/
//
// Dialog
//

IDD_DIALOG1 DIALOGEX 0, 0, 354, 138
STYLE DS_SETFONT | WS_CHILD | WS_SYSMENU
FONT 9, "新宋体", 400, 0, 0x0
BEGIN
    LTEXT           "串口号: ",IDC_STATIC,14,18,33,8
    COMBOBOX        IDC_COMBO1,52,15,81,30,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
    DEFPUSHBUTTON   "连接",IDOK,137,15,50,14
    CTEXT           "未连接串口",IDC_STATIC2,197,14,139,37,SS_CENTERIMAGE | SS_SUNKEN
    CONTROL         "模式1",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,52,39,36,10
    CONTROL         "模式2",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,105,39,36,10
    CONTROL         "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,63,340,1
    CONTROL         "电池电压",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,115,81,48,10
    EDITTEXT        IDC_EDIT1,170,79,67,14,ES_AUTOHSCROLL | WS_DISABLED
    LTEXT           "V",IDC_STATIC,242,82,8,8
    CONTROL         "温度",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,115,105,32,10
    EDITTEXT        IDC_EDIT2,170,103,40,14,ES_AUTOHSCROLL | WS_DISABLED
    CONTROL         "",IDC_SPIN1,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | WS_DISABLED,263,103,11,14
    LTEXT           "℃",IDC_STATIC,214,106,15,8
END

IDD_DIALOG2 DIALOGEX 0, 0, 354, 138
STYLE DS_SETFONT | WS_CHILD | WS_SYSMENU
FONT 9, "新宋体", 400, 0, 0x0
BEGIN
    CONTROL         "",IDC_LIST1,"SysListView32",WS_BORDER | WS_TABSTOP,7,7,338,121
END

IDD_TABBOX DIALOGEX 0, 0, 374, 166
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "移除选项卡灰色背景"
FONT 9, "新宋体", 400, 0, 0x0
BEGIN
    CONTROL         "",IDC_TAB1,"SysTabControl32",0x0,7,7,360,152
END


/
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
    IDD_DIALOG1, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 347
        TOPMARGIN, 7
    END

    IDD_DIALOG2, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 345
        TOPMARGIN, 7
    END

    IDD_TABBOX, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 309
        TOPMARGIN, 7
    END
END
#endif    // APSTUDIO_INVOKED

#endif    // 中文(简体,中国) resources
/



#ifndef APSTUDIO_INVOKED
/
//
// Generated from the TEXTINCLUDE 3 resource.
//


/
#endif    // not APSTUDIO_INVOKED


http://www.niftyadmin.cn/n/5546929.html

相关文章

接口测试(3)

接口自动化 # 获取图片验证码import requestsresponse requests.get(url"http://kdtx-test.itheima.net/api/captchaImage")print(response.status_code) print(response.text) import requestsurl "http://kdtx-test.itheima.net/api/login" header_da…

Jmeter进阶-接口自动化

JMeter 是一款广泛使用的开源软件,它不仅可以用于性能测试,还可以用于接口自动化测试。以下是 JMeter 进行接口自动化测试的一些优缺点: 优点: 易用性:JMeter 上手简单,大部分操作都有对应的元件帮助完成,开源且社区接受度高 。灵活性:提供 BeanShell 脚本能力,允许自…

springboot 与 ipv6

ipv6 是个必然趋势&#xff0c;尤其最近国家在这方面有新的推动。 运营商的项目逐渐有这方面的要求了。 所以&#xff0c;在ipv6环境&#xff0c;http或者https接口&#xff0c;还有数据库地址&#xff0c;ipv4下是ip:port&#xff0c; 但到了ipv6&#xff0c;ipv6 的 ip就包含…

一体化运维:某省电力公司实现集中统一监控

在当今信息化高速发展的时代&#xff0c;电力公司作为国家基础设施的重要组成部分&#xff0c;其IT系统的稳定性和高效性直接关系到电力供应的安全与稳定。为了提升运维效率&#xff0c;确保电力系统的持续稳定运行&#xff0c;某省电力公司采购十多套“监控易”运维软件&#…

科普文本分类背后的数学原理——最新版《数学之美》第14、15章读书笔记

新闻分类&#xff0c;或广义上的文本分类&#xff0c;其核心任务是根据文本内容将相似文本聚合在同一类别中。在新闻领域&#xff0c;这意味着将报道划分为财经、体育、军事等不同主题。人类执行此任务时&#xff0c;通过阅读和理解新闻的主旨来进行归类。然而&#xff0c;作者…

opencv读取视频文件夹内视频的名字_时长_帧率_分辨率写入excel-cnblog

看视频的时候有的视频文件名贼长。想要翻看&#xff0c;在文件夹里根本显示不出来&#xff0c;缩短又会丢失一些信息&#xff0c;所以我写了一份Python代码&#xff0c;直接获取视频的名字&#xff0c;时长&#xff0c;帧率&#xff0c;还有分辨率写到excel里。 实际效果如下图…

Spring-AOP(二)

作者&#xff1a;月下山川 公众号&#xff1a;月下山川 1、什么是AOP AOP&#xff08;Aspect Oriented Programming&#xff09;是一种设计思想&#xff0c;是软件设计领域中的面向切面编程&#xff0c;它是面向对象编程的一种补充和完善&#xff0c;它以通过预编译方式和运行期…

LCR 155. 将二叉搜索树转化为排序的双向链表

力扣链接https://leetcode.cn/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/description/ 解题思路 中序遍历可以得到排序的序列&#xff0c;遍历时维护当前节点和前一个节点&#xff0c;改变左右指针。头节点设为null&#xff0c;遍历开始判断一下然后初始化。…