热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Win32子窗口及其创建应用

简介:所谓的子窗口就是一个父窗口里的一个窗口,父窗口也叫主窗口。子窗口也是窗口,它有自己的回调函数、自己的窗口类、自己的创建。它位于主窗口里的一个区域,我们可以设置子窗口的大小和位



简介:

所谓的子窗口就是一个父窗口里的一个窗口,父窗口也叫主窗口。子窗口也是窗口,它有自己的回调函数、自己的窗口类、自己的创建。它位于主窗口里的一个区域,我们可以设置子窗口的大小和位置以及相关属性。子窗口与主窗口之间是相联系的,它们通过句柄和消息等访问彼此的。


特别提醒:

后面所讲的子窗口控件是一种特殊的子窗口。子窗口控件不需要我们来定义窗口类,系统已经帮我们定义好了,我们自己引用就好。


这里我们先介绍普通子窗口。




一、子窗口的创建

创建过程:

1.注册窗口类(我们在主窗口注册后面接着注册子窗口)

2.创建子窗口(一般在WS_CREATE消息处理中创建,和创建主窗口一样使用CreateWindow函数,参数不同哦,需加上WS_CHILD和WS_VISIBLE风格)

3.定义子窗口的回调函数(子窗口回调函数和主窗口回调函数大致一样,改下函数名)



1.注册窗口类

子窗口类参数基本和主窗口一样,一般只需修改一下四个参数即可。

// 注册主窗口后面,修改四个参数
wc.cbClsExtra = sizeof(long); // 预留空间
wc.hIcon = NULL; // 图标设为空
wc.lpfnWndProc = ChildWndProc; // 回调函数
wc.lpszClassName = TEXT("ChildWindow"); // 子窗口类名
// 注册子窗口类
RegisterClassEx(&wc);

2.创建子窗口

CreateWindow参数的比较:



































































参数主窗口子窗口
窗口类名自己定义自己定义
窗口标题自己定义NULL
窗口样式WS_OVERLAPPEDWINDOWWS_CHILDWINDOWWS_VISIBLE
水平位置CW_USEDEFAULT0(后面可通过MoveWindow函数修改)
垂直位置CW_USEDEFAULT0(后面可通过MoveWindow函数修改)
宽度CW_USEDEFAULT0(后面可通过MoveWindow函数修改)
高度CW_USEDEFAULT0(后面可通过MoveWindow函数修改)
父窗口句柄NULLhwnd
菜单句柄/子IDNULL(HMENU) (y <<8 |x) 不同子ID就行
实体句柄hInstance(HINSTANCE)GetWindowLong (hwnd, GWL_HINSTANCE)(LPCREATESTRUCT)lParam->hInstance
额外参数lParamNULLNULL

子窗口是否显示可调用ShowWindow函数进行修改,窗口的大小、位置可以通过MoveWindow函数进行修改。

// 创建25个子窗口
case WM_CREATE:
{
for (i = 0; i <5; i++)
{
for (j = 0; j <5; j++)
{
childhwnd[i][j]=CreateWindow(TEXT("ChildWindow"), NULL,
WS_CHILD|WS_VISIBLE,
0, 0, 0 ,0,
hwnd, (HMENU)(x++),
(HINSTANCE)GetWindowLong (hwnd, GWL_HINSTANCE), NULL);
}
}
break;
}

3.定义子窗口回调函数

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam); // 主窗口回调函数
LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam); // 子窗口回调函数
LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
case WM_LBUTTONDOWN:
{
ShowWindow(hwnd, SW_HIDE);
break;
}
default:
return DefWindowProc(hwnd, Message, wParam, lParam); //让系统处理消息,这条语句一定要加上
}
return 0;
}



二、子窗口与主窗口的联系

1.主窗口访问子窗口(发送消息)



  • 获取窗口信息:GetWindowLongPrt

  • 获取指定控件的ID号: GetDlgCtrlID

  • 获取指定ID的句柄:GetDlgItem

  • 改变指定窗口的位置和大小: MoveWindow

  • 将指定的消息发送到一个或多个窗口:SendMessage


GetWindowLongPrt函数:获取窗口信息

LONG_PTR GetWindowLongPtr(HWND hWnd, // 窗口句柄
int nIndex); // 获取的信息指定值


















































参数含义
GWL_EXSTYLE获取扩展窗口样式。更多信息,查阅CreateWindowEx.
GWL_STYLE获取窗口样式(window styles)
GWLP_WNDPROC获取窗口程序指示器,或描述指示器的句柄 。如果使用此参数,必须使用CallWindowProc回调函数。
GWLP_HINSTANCE获取一个应用程序实例的句柄 。
GWLP_HWNDPARENT如果只有一个父窗口,获取父窗口的句柄 。
GWLP_ID获取窗口标识符。
GWLP_USERDATA获取窗口关联的数据,是应用程序创建窗口时留给用户的数据。初始值是0。
DWLP_DLGPROC获取一个对话框的指示器,或描述指示器的句柄 。如果使用此参数,必须使用CallWindowProc回调函数。
DWLP_MSGRESULT获取一个对话框中的被处理的信息的值。
DWLP_USER作为指示器或句柄来获取私有应用程序的额外的信息。

GetDlgCtrlID函数:获取指定控件的ID号

ID是针对子窗体而言的,窗体时把这个ID号传递给hMenu参数。

int GetDlgCtrlID(HWND hwndCtl); // 子窗口句柄


GetDlgItem函数:获取指定ID的句柄

HWND childhwnd = GetDlgItem(Parenthwnd,ID);


MoveWindow函数:改变指定窗口的位置和大小

对基窗口来说,位置和大小取决于屏幕的左上角;对子窗口来说,位置和大小取决于父窗口客户区的左上角.对于Owned窗口,位置和大小取决于屏幕左上角.

BOOL MoveWindow( HWND hWnd, int X, int Y, int nWidth, int nHeight,
BOOL bRepaint ); // TRUE重画,FALSE不重画


SendMessage函数:将指定的消息发送到一个或多个窗口

SendMessage函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。

PostMessage函数是将一个消息寄送到一个线程的消息队列后就立即返回。

LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam)


2.子窗口访问主窗口(发送消息)



  • 获得一个指定子窗口的父窗口句柄:GetParent

  • 将指定的消息发送到一个或多个窗口:SendMessage

HWND GetParent(HWND hWnd);



三、子窗口的应用:翻牌

简介:

这里创建了25个子窗口,开始设置25个子窗口都可见,后面主窗口和子窗口分别相应鼠标左键按下的消息,主窗口收到消息显示子窗口,子窗口收到消息隐藏子窗口,ShowWindow可以实现。子窗口显示时就看不到图片,子窗口不显示能看到图片。子窗口隐藏状态时,子窗口就消失了,不能接受鼠标按下消息了。这里需要注意的是,当我们点击子窗口时,主窗口是收不到按键消息的,子窗口通过自己的回调函数处理消息。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

代码如下:有注释的

#include
#include"strsafe.h" // 安全字符串操作
// 定义回调函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);
HINSTANCE hInst; // 用来保存实例句柄,在下面创建子窗口CreateWindow用到
#define NUM 5 // 宏定义
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
WNDCLASSEX wc;
HWND hwnd;
MSG msg;
// 注册主窗口类
memset(&wc, 0, sizeof(wc));
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszClassName = TEXT("WindowClass");
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIcOnSm= LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc)) {
MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"), MB_ICONEXCLAMATION | MB_OK);
return 0;
}

// 注册子窗口类
wc.cbClsExtra = sizeof(long);
wc.hIcon = NULL;
wc.lpfnWndProc = ChildWndProc;
wc.lpszClassName = TEXT("ChildWindow");
RegisterClassEx(&wc);
// 创建主窗口
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("WindowClass"), TEXT("Caption"), WS_CAPTION|WS_SYSMENU,
CW_USEDEFAULT, /* x */
CW_USEDEFAULT, /* y */
520, /* width */
542, /* height */
NULL, NULL, hInstance, NULL);
hInst = hInstance; // 保存实例句柄
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
if (hwnd == NULL) {
MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"), MB_ICONEXCLAMATION | MB_OK);
return 0;
}
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
// 主函数回调函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc,mdc;
static int cxClient, cyClient,x=0,cx,cy;
static HWND childhwnd[NUM][NUM];
HBITMAP bmp;
int i, j;
WCHAR str[100];
switch (Message)
{
// 创建25个子窗口
case WM_CREATE:
{
for (i = 0; i {
for (j = 0; j {
childhwnd[i][j]=CreateWindowEx(0,TEXT("ChildWindow"), NULL, WS_CHILD|WS_VISIBLE,
100*i, /* x */
100*j, /* y */
98, /* width */
98, /* height */
hwnd, (HMENU)(x++), hInst, NULL);
}
}
break;
}

// 将赵丽颖美图贴上去,前面博客有讲
case WM_PAINT:
{
hdc = BeginPaint(hwnd, &ps);
mdc = CreateCompatibleDC(hdc);
bmp = (HBITMAP)LoadImage(hInst, MAKEINTRESOURCEW(101), IMAGE_BITMAP, 500, 500, LR_CREATEDIBSECTION);
SelectObject(mdc, bmp);
BitBlt(hdc, 0, 0, 500, 500, mdc, 0, 0, SRCCOPY);
EndPaint(hwnd, &ps);
break;
}
// 主窗口响应左键,显示子窗口
case WM_LBUTTONDOWN:
{
cx = LOWORD(lParam);
cy = HIWORD(lParam);
i = cx/100;
j = cy/100;
ShowWindow(childhwnd[i][j], SW_SHOW); // 显示子窗口

break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
default:
return DefWindowProc(hwnd, Message, wParam, lParam);
}
return 0;
}
// 子窗口回调函数
LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
switch(Message)
{
// 子窗口响应左键,隐藏子窗口
case WM_LBUTTONDOWN:
{
ShowWindow(hwnd, SW_HIDE);
break;
}

// 其他消息处理,不能忘记啊
default:
return DefWindowProc(hwnd, Message, wParam, lParam);
}
return 0;
}


作者说:

这世道真的是人善被人欺!你越不反抗,别人越没有什么畏惧,就喜欢来惹事欺负,她总以为自己有多么了不起。妈的,你们一家子是看着我妈好欺负是吧,有事没事就对我妈发脾气骂人,我妈这才上去几天,都到我妈住的地方故意来找事了,骂的话还那么难听,真的,要是我不在,不然我真想冲上去,我妈本来就身体不好,不能着急的,心疼我妈。这人真的是,自己人品有问题还说我妈,要是你人好,怎么会和自己婆婆一见面就吵架,都呆在娘家二十几年了吧,你有本事咋不回去,在厂里干个活,三天两天不是和这个吵就是和那个吵,和我妈还是娘家的表姐妹,有这样做姐妹的呀,我是天底下没见过,既然你们一家子也说了,亲戚能走就走,不能走就不走,我也觉得这样最好,我以后也不希望能沾你们的光,大路朝天各走一边。别人骂我妈心里不好受,在这里吐槽一下,希望大家理解。



推荐阅读
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文介绍了RxJava在Android开发中的广泛应用以及其在事件总线(Event Bus)实现中的使用方法。RxJava是一种基于观察者模式的异步java库,可以提高开发效率、降低维护成本。通过RxJava,开发者可以实现事件的异步处理和链式操作。对于已经具备RxJava基础的开发者来说,本文将详细介绍如何利用RxJava实现事件总线,并提供了使用建议。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • 如何在HTML中获取鼠标的当前位置
    本文介绍了在HTML中获取鼠标当前位置的三种方法,分别是相对于屏幕的位置、相对于窗口的位置以及考虑了页面滚动因素的位置。通过这些方法可以准确获取鼠标的坐标信息。 ... [详细]
author-avatar
NewGuy
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有