DuiLib窗体之ShowWindow()和ShowModal()函数分析以及duilib控件的一些属性

Create函数说明前言

HWND CWindowWnd::Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, int x, int y, int cx, int cy, HMENU hMenu)
{
    
    
    if( GetSuperClassName() != NULL && !RegisterSuperclass() ) return NULL;
    if( GetSuperClassName() == NULL && !RegisterWindowClass() ) return NULL;
    m_hWnd = ::CreateWindowEx(dwExStyle, GetWindowClassName(), pstrName, dwStyle, x, y, cx, cy, hwndParent, hMenu, CPaintManagerUI::GetInstance(), this);
    ASSERT(m_hWnd!=NULL);
    return m_hWnd;
}

1、窗体创建过程

在文章《Windows消息机制的逆向分析》中详细分析了Windows的消息机制以及窗体的创建过程,文章中表述Windows窗体的创建分为三步:声明WNDCLASS实例、窗体注册、创建窗体。如果继续细分可以分为四步:声明WNDCLASS实例、窗体注册、创建窗体、显示窗体。

其中窗体注册函数是RegisterClass()RegisterClassEx(),创建窗体则是CreateWindow()CreatewindowEx()函数,显示窗体则是利用ShowWindow() 函数。

本文重点描述ShowWindow() 函数。

2、ShowWindow函数

CreateWindowEx 建立窗口以后,这时候,窗口虽已建立,但还没有在屏幕上显示出来。

3、 ShowWindow函数

函数功能:该函数设置指定窗口的显示状态。

函数原型:BOOL ShowWindow(HWND hWnd, int nCmdShow)

其中hWnd指窗口句柄;nCmdShow指定窗口如何显示。如果发送应用程序的程序提供了STARTUPINFO结构,则应用程序第一次调用ShowWindow时该参数被忽略。否则,在第一次调用ShowWindow函数时,该值应为在函数WinMainnCmdShow参数。在随后的调用中,该参数可以为下列值之一:

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPTSTR    lpCmdLine,
	_In_ int       nCmdShow)

在这里插入图片描述

void ShowWindow(bool bShow = true, bool bTakeFocus = true);
void CWindowWnd::ShowWindow(bool bShow /*= true*/, bool bTakeFocus /*= false*/)
{
    
    
    ASSERT(::IsWindow(m_hWnd));
    if( !::IsWindow(m_hWnd) ) return;
    ::ShowWindow(m_hWnd, bShow ? (bTakeFocus ? SW_SHOWNORMAL : SW_SHOWNOACTIVATE) : SW_HIDE);
}

4、ShowModal()函数

void ShowModal(HWND hWndParent = ::GetActiveWindow())

功能:以模态方式显示窗口,即在窗口未关闭之前,用户无法与其他窗口进行交互。

参数:

  • hWndParent:可选参数,指定父窗口的句柄,默认为当前活动窗口的句柄。如果指定了父窗口句柄,那么该窗口将作为模态对话框的父窗口。

5、duilib控件的一些属性

5.1、Windows控件

Create	创建窗口
Close	关闭窗口
ShowWindow	显示或隐藏窗口
ShowModalFake	显示模态对话框(推荐)
CenterWindow	居中窗口,支持扩展屏幕
Init	窗口接收到 WM_CREATE 消息时会被调用,一般用于初始化
AttachDialog	绑定窗口的顶层容器
InitControls	初始化控件,在容器中添加控件时会被调用(用于对控件名称做缓存)
ReapObjects	回收控件
GetWindowResourcePath	获取窗口资源路径
SetWindowResourcePath	设置窗口资源路径
GetDefaultFontInfo	获取默认字体信息

5.2、Control控件

接口名称	用途
GetParent	获取父容器指针
GetAncestor	根据名称获取祖先容器指针
GetName	获取控件名称,对应 xml 中 name 属性
GetUTF8Name	获取控件名称,对应 xml 中 name 属性
SetName	设置控件名称,内存中设置不会写入 xml 中
SetUTF8Name	设置控件名称,内存中设置不会写入 xml 中(UTF8 编码)
GetWindow	获取关联的窗口指针
SetWindow	设置容器所属窗口
Init	初始化函数
DoInit	由 Init 调用,功能与 Init 相同
IsVisible	判断是否可见
IsInternVisible	待补充
IsFloat	判断控件是否浮动,对应 xml 中 float 属性
SetFloat	设置控件是否浮动
GetFixedWidth	获取固定宽度,对应 xml 中 width 属性
SetFixedWidth	设置控件固定宽度
GetFixedHeight	获取固定高度
SetFixedHeight	设置固定高度
GetMinWidth	获取最小宽度
SetMinWidth	设置最小宽度
GetMaxWidth	获取最大宽度
SetMaxWidth	设置最大宽度
GetMinHeight	获取最小高度
SetMinHeight	设置最小高度
GetMaxHeight	获取最大高度
SetMaxHeight	设置最大高度
GetWidth	获取实际宽度
GetHeight	获取实际高度
GetHorAlignType	获取水平对齐方式
SetHorAlignType	设置水平对齐方式
GetVerAlignType	获取垂直对齐方式
SetVerAlignType	设置垂直对齐方式
IsReEstimateSize	待补充
SetReEstimateSize	待补充
EstimateSize	待补充
GetPos	获取控件位置
SetPos	设置控件位置
Arrange	进行布局
ArrangeAncestor	让父容器排列
IsArranged	判断是否已经排列过
Invalidate	重绘控件
GetPosWithScrollOffset	待补充
GetScrollOffset	待补充
ArrangeSelf	待补充
GetBkColor	获取背景颜色
SetBkColor	设置背景颜色
GetStateColor	获取某个状态下的字体颜色
SetStateColor	设置某个状态下的字体颜色
GetBkImage	获取背景图片位置
GetUTF8BkImage	获取 UTF8 格式的背景图片位置
SetBkImage	设置背景图片
SetUTF8BkImage	设置背景图片(UTF8 格式字符串)
GetStateImage	获取指定状态下的图片位置
SetStateImage	设置某个状态下的图片
GetForeStateImage	获取指定状态下的前景图片
SetForeStateImage	设置某个状态下前景图片
GetState	获取控件状态
SetState	设置控件状态
GetEstimateImage	获取控件图片指针
GetBorderSize	获取边框大小
SetBorderSize	设置边框大小
GetBorderColor	获取边框颜色
SetBorderColor	设置边框颜色
SetBorderSize	设置边框的大小
GetLeftBorderSize	获取左侧边框大小
SetLeftBorderSize	设置左侧边框大小
GetTopBorderSize	获取顶部边框大小
SetTopBorderSize	设置顶部边框大小
GetRightBorderSize	获取右侧边框大小
SetRightBorderSize	设置右侧边框大小
GetBottomBorderSize	获取下方边框大小
SetBottomBorderSize	设置下方边框大小
GetBorderRound	获取边框大小
SetBorderRound	设置边框大小
GetCursorType	获取鼠标指针类型
SetCursorType	设置当前鼠标指针类型
GetToolTipText	获取控件在鼠标悬浮状态下的提示文本
GetUTF8ToolTipText	获取控件在鼠标悬浮状态下的提示文本(UTF8 格式)
SetToolTipText	设置鼠标悬浮到控件显示的提示文本
SetUTF8ToolTipText	设置鼠标悬浮到控件显示的提示文本(UTF8 格式)
SetToolTipTextId	设置鼠标悬浮到控件显示的提示文本在语言文件中对应的文字
SetUTF8ToolTipTextId	设置鼠标悬浮到控件显示的提示文本在语言文件中对应的文字(UTF8 格式)
SetToolTipWidth	设置鼠标悬浮到控件上提示的文本单行最大宽度
GetToolTipWidth	获取鼠标悬浮到控件上提示的文本单行最大宽度
IsContextMenuUsed	控件是否响应右键菜单消息
SetContextMenuUsed	设置控件响应右键菜单消息
GetDataID	获取用户绑定到控件的数据字符串
GetUTF8DataID	获取用户绑定到控件的数据字符串(UTF8 格式)
SetDataID	绑定一个字符串数据到控件
SetUTF8DataID	绑定一个字符串数据到控件(UTF8 格式)
GetUserDataBase	获取用户绑定的自定义数据结构
SetUserDataBase	绑定自定义数据到控件,用户可继承 UserDataBase 来补充需要绑定的数据
SetVisible	设置控件是否可见
SetInternVisible	待补充
SetVisible_	待补充
IsEnabled	检查控件是否可用
SetEnabled	设置控件可用状态
IsMouseEnabled	检查控件是否响应鼠标事件
SetMouseEnabled	设置控件是否响应鼠标事件
IsKeyboardEnabled	检查控件是否响应键盘事件
SetKeyboardEnabled	设置控件是否响应键盘事件
IsFocused	检查控件是否具有焦点
SetFocus	让控件获取焦点
SetNoFocus	让控件设置永远获取不到焦点
GetControlFlags	返回控件的标识,用于判断是否可以响应 TAB 切换事件
IsMouseFocused	判断当前鼠标焦点是否在控件上
SetMouseFocused	设置是否将鼠标焦点到控件上
IsActivatable	判断控件当前是否是激活状态
Activate	待补充
FindControl	根据坐标查找指定控件
GetPos	获取控件位置
SetPos	设置控件位置
GetMargin	获取控件的外边距
SetMargin	设置控件的外边距
EstimateSize	计算控件大小
EstimateText	待补充
IsPointInWithScrollOffset	检查指定坐标是否在滚动条当前滚动位置的范围内
HasHotState	判断控件是否处于 HOT 状态
SetReceivePointerMsg	设置控件是否响应触控消息
IsReceivePointerMsg	判断控件是否响应触控消息
SetNeedButtonUpWhenKillFocus	设置控件失去焦点时是否发送鼠标弹起消息
IsNeedButtonUpWhenKillFocus	判断控件失去焦点时是否发送鼠标弹起消息
SetAttribute	设置控件指定属性
SetClass	设置控件的 class 全局属性
ApplyAttributeList	应用一套属性列表
OnApplyAttributeList	待补充
HandleMessageTemplate	控件统一的消息处理入口,将传统 Windows 消息转换为自定义格式的消息
HandleMessageTemplate	将转换后的消息派发到消息处理函数
GetImage	根据图片路径缓存图片信息
DrawImage	绘制图片
GetRenderContext	获取绘制上下文对象
ClearRenderContext	清理绘制上下文对象
AlphaPaint	待补充
Paint	绘制控件的入口函数
PaintChild	绘制控件子项入口函数
SetClip	设置是否对绘制范围做剪裁限制
IsClip	判断是否对绘制范围做剪裁限制
SetAlpha	设置控件透明度
GetAlpha	获取控件透明度
IsAlpha	检查控件是否有透明属性
SetHotAlpha	设置焦点状态透明度
GetHotAlpha	获取焦点状态透明度
GetRenderOffset	获取控件绘制偏移量
SetRenderOffset	设置控件绘制偏移量
SetRenderOffsetX	设置控件偏移的 X 坐标
SetRenderOffsetY	设置控件偏移的 Y 坐标
StartGifPlayForUI	播放 GIF
StopGifPlayForUI	停止播放 GIF
AttachGifPlayStop	监听 GIF 播放完成通知

6、ShowWindow() 和 ShowModal()区别

  • ShowWindow() 用于以非模态方式显示窗口,窗口会显示在屏幕上,并且用户可以与其他窗口进行交互,即可同时操作多个窗口。
  • ShowModal() 用于以模态方式显示窗口,窗口会显示在屏幕上,但用户在与该窗口交互时,无法同时操作其他窗口,直到该模态窗口被关闭。

在使用时,根据具体的需求和交互方式,选择适合的函数来显示窗口,以实现期望的用户体验。如果希望窗口以非模态方式显示,允许用户与其他窗口进行交互,可以使用 ShowWindow();如果希望窗口以模态方式显示,阻塞用户与其他窗口的交互,直到模态窗口关闭,可以使用 ShowModal()

6.1、DuiLib中的非模式方式和模式方式区别

  • 显示方式
    • 非模态方式:窗口以非模态方式显示,不会阻塞用户与其他窗口进行交互。用户可以同时操作多个窗口,并且可以在窗口之间自由切换。
    • 模态方式:窗口以模态方式显示,阻塞用户与其他窗口的交互。在模态窗口打开期间,用户只能与该窗口进行交互,无法操作其他窗口,直到模态窗口被关闭。
  • 用户交互
    • 非模态方式:用户可以在窗口显示的同时,与其他窗口进行交互。比如,在一个编辑窗口中编辑文本内容时,仍然可以点击其他窗口或执行其他操作。
    • 模态方式:用户只能与模态窗口进行交互,无法在模态窗口打开期间切换到其他窗口。这样可以确保用户专注于与模态窗口进行交互,直到完成相应的操作。
  • 窗口间的关系
    • 非模态方式:窗口之间没有直接的父子关系,它们是独立的顶级窗口,可以同时存在于屏幕上。
    • 模态方式:模态窗口有一个父窗口,通常是打开它的窗口。模态窗口被打开时,会将父窗口置为不可操作状态,只有在模态窗口关闭后,父窗口才恢复可操作状态。
  • 关闭方式
    • 非模态方式:非模态窗口可以通过关闭按钮或其他操作进行关闭。
    • 模态方式:模态窗口通常有确定或取消按钮,用户必须通过这些按钮来关闭模态窗口。
      总结:

非模态方式适用于用户可以同时操作多个窗口的情况,不会阻塞用户与其他窗口的交互。
模态方式适用于需要用户专注于特定任务或操作的情况,它会阻塞用户与其他窗口的交互,直到模态窗口完成任务或关闭。

非模态方式(非模态对话框)和模态方式(模态对话框)是两种不同的窗口显示方式,它们在用户交互和应用程序行为方面有一些区别。

  • 非模态方式(非模态对话框)

    • 特点:以非模态方式显示的窗口不会阻塞用户与其他窗口进行交互。
    • 用户交互:用户可以同时操作多个窗口,包括与其他应用程序窗口进行交互,无需等待该窗口关闭。
    • 应用程序行为:非模态对话框通常用于显示临时性的信息、选项或功能,用户可以自由地在不同窗口之间切换和操作。
  • 模态方式(模态对话框)

    • 特点:以模态方式显示的窗口会阻塞用户与其他窗口进行交互。
    • 用户交互:用户只能与该模态对话框进行交互,无法与其他窗口进行交互,直到模态对话框关闭。
    • 应用程序行为:模态对话框通常用于显示重要的信息、必须要用户确认或提供必填项的情况,确保用户在处理对话框内容时不能切换到其他窗口,直到对话框关闭。

总结:
非模态对话框适合用于用户可以同时操作多个窗口的场景,适用于一般信息展示和临时性功能。
模态对话框适用于需要用户集中注意力处理的情况,确保用户不能切换到其他窗口,以防止忽略或遗漏重要信息。

6.2、ShowWindow()模式中使用MessageLoop()和ShowModal()不使用MessageLoop()

  • ShowWindow()
    • ShowWindow() 是以非模态方式显示窗口,即窗口在显示的同时,用户可以与其他窗口进行交互。
    • 一般情况下,在使用 ShowWindow() 时,你需要在主消息循环中添加消息处理函数,以响应窗口的消息,处理窗口中的交互和事件。
    • 主消息循环通常是一个无限循环,不断接收并分发消息,直到程序退出。
  • ShowModal()
    • ShowModal() 是以模态方式显示窗口,即在窗口未关闭之前,用户无法与其他窗口进行交互。
    • 在使用 ShowModal() 时,不需要单独创建消息循环。DuiLib 中的 ShowModal() 方法会在内部启动一个模态消息循环,直到模态对话框被关闭,才会返回到 ShowModal() 调用的地方。
    • ShowModal() 的调用将阻塞程序的执行,直到模态对话框关闭,再继续执行后续代码。

示例:

// 使用 ShowWindow()
CPaintManagerUI::SetInstance(hInstance);
CPaintManagerUI::SetCurrentPath(CPaintManagerUI::GetInstancePath());

CMainDlg *pFrame = new CMainDlg;
pFrame->Create(NULL, _T("DUIWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
pFrame->ShowWindow();
CPaintManagerUI::MessageLoop();

// 使用 ShowModal()
CMainDlg *pFrame = new CMainDlg;
pFrame->Create(NULL, _T("DUIWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
pFrame->ShowModal();

总结:

  • ShowWindow() 需要自行创建主消息循环,并在其中处理窗口消息和事件。
  • ShowModal() 内部启动了模态消息循环,不需要单独创建消息循环,会阻塞程序的执行,直到模态对话框关闭。

猜你喜欢

转载自blog.csdn.net/qq_44918090/article/details/131781747
今日推荐