MFC显示窗口时关于GetWindowRect()、GetClientRect()、ClientToScreen()和SetWindowPos()等方法的一些Tips

网上看了一些资料,对于MFC显示位置坐标等说明文档主要是讨论GetWindowRect()与GetClientRect(),由于最近修改公司项目上的一些小问题是遇到相关内容,因此记录一下便于以后查找。感觉网友们形容的已经很详细了,所以在这参考一些MSDN上的说明和网友博客中的一些内容,并小小的测试几个细节问题。

对于GetWindowRect()解释在MSDN上写的非常明白:

This function retrieves the dimensions of the bounding rectangle of the specified window. The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen. 

给函数获取窗口边框位置尺寸,且提供的信息是相对屏幕左上角位置。

对于GetClientRect()函数,也有相应解释,清晰明了:

Retrieves the coordinates of a window's client area. The client coordinates specify the upper-left and lower-right corners of the client area. Because client coordinates are relative to the upper-left corner of a window's client area, the coordinates of the upper-left corner are (0,0).

 获取用户区域位置尺寸,最后一句已经写清楚得到位置坐标即为左上角坐标值为(0,0)。

下面进行一个非常简单而又草率的测试。

 我用this和IDC_STATIC控件(随便拖了个Picture Control进去)分别调用两种方法,当我的主窗口11111在随机位置时,得到结果如下:

 

这个已经非常简单明了了吧,完全符合说明文档字面意思,要说明的一点是有位老铁在博客中说一个没有父类的窗口调用GetWindowRect()后会显示位置坐标为(0,0),调用某控件时才会出现相对屏幕左上角位置的坐标值。再次我只想问一句这位老铁你是不是把窗口给最大化,或对齐到了屏幕左上角后进行的测试。。。在那种情况下时你的主窗口位置与屏幕左上角坐标重合导致的坐标(0,0)。

顺便再提一句ScreenToClient() 就是把屏幕坐标系下的RECT坐标转换为客户区坐标系下的RECT坐标,其实通俗点说我们调用GetWindowRect()后再调用ScreenToClient()的效果和直接使用GetClientRect()没什么区别,但通过调用两个方法实现提供的信息是多于只使用GetClientRect()的,因此也要根据具体情况安排。

当然ClientToScreen()方法的使用和ScreenToClient()的使用方法没什么区别,根据字面意思也很好理解。

其实我想记录的主要问题是关于使用SetWindowPos()方法操作一些窗口的显示顺序。因为最近工程上的一些小bug,简单来说就是我的pc端程序线程比较复杂,功能端交互和显示界面比较多,且需要和设备A(Linux环境)端进行通信,设备A还要去驱动另一个带有工业相机和操作板的设备B。维护程序时发现正常操作设备B控制PC端的某些功能界面端显示正常,一旦我将程序最小化隐藏后,再通过设备B的按键响应操作PC端程序就会在UI显示上出现一些异常。由于属于小问题,而我又懒得去解析CWnd::OnSysCommand()方法,因此只考虑在恢复程序界面前端显示时重置一下需求界面的位置顺序。这里要使用SetWindowPos()方法来实现,可以参考以下函数:

BOOL SetWindowPos(
  HWND hWnd,
  HWND hWndInsertAfter,
  int  X,
  int  Y,
  int  cx,
  int  cy,
  UINT uFlags
);

在MSDN中只找到上述引用,而在MFC中我们常使用:

BOOL SetWindowPos(HWND hWndlnsertAfter, int X,int Y,int cX,int cY,UNIT Flags);

下面搬运一些简单说明和操作方便以后使用:

hWndInsertAfter

Type: HWND

A handle to the window to precede the positioned window in the Z order. This parameter must be a window handle or one of the following values.

ValueMeaning

HWND_BOTTOM

(HWND)1

Places the window at the bottom of the Z order. If the hWnd parameter identifies a topmost window, the window loses its topmost status and is placed at the bottom of all other windows.

将窗口置于Z序的底部;

HWND_NOTOPMOST

(HWND)-2

Places the window above all non-topmost windows (that is, behind all topmost windows). This flag has no effect if the window is already a non-topmost window.

将窗口置于所有非顶层窗口之上(即在所有顶层窗口之后);

HWND_TOP

(HWND)0

Places the window at the top of the Z order.

将窗口置于Z序的顶部;

HWND_TOPMOST

(HWND)-1

Places the window above all non-topmost windows. The window maintains its topmost position even when it is deactivated.

将窗口置于所有非顶层窗口之上。即使窗口未被激活窗口也将保持顶级位置。

 其中的X,Y,Cx,Cy解释为:The new position of the left /top side of the window, in client coordinates. and The new width/height  of the window, in pixels.

 uFlags

Type: UINT

The window sizing and positioning flags. This parameter can be a combination of the following values.

ValueMeaning

SWP_ASYNCWINDOWPOS

0x4000

If the calling thread and the thread that owns the window are attached to different input queues, the system posts the request to the thread that owns the window. This prevents the calling thread from blocking its execution while other threads process the request.

如果调用进程不拥有窗口,系统会向拥有窗口的线程发出需求。这就防止调用线程在其他线程处理需求的时候发生死锁。

SWP_DEFERERASE

0x2000

Prevents generation of the WM_SYNCPAINT message.

防止产生WM_SYNCPAINT消息。

SWP_DRAWFRAME

0x0020

Draws a frame (defined in the window's class description) around the window.

在窗口周围画一个边框(定义在窗口类描述中)。

SWP_FRAMECHANGED

0x0020

Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE is sent only when the window's size is being changed.

给窗口发送WM_NCCALCSIZE消息,即使窗口尺寸没有改变也会发送该消息。如果未指定这个标志,只有在改变了窗口尺寸时才发送WM_NCCALCSIZE。

SWP_HIDEWINDOW

0x0080

Hides the window.

隐藏窗口。

SWP_NOACTIVATE

0x0010

Does not activate the window. If this flag is not set, the window is activated and moved to the top of either the topmost or non-topmost group (depending on the setting of the hWndInsertAfter parameter).

不激活窗口。如果未设置标志,则窗口被激活,并被设置到其他最高级窗口或非最高级组的顶部(根据参数hWndlnsertAfter设置)。

SWP_NOCOPYBITS

0x0100

Discards the entire contents of the client area. If this flag is not specified, the valid contents of the client area are saved and copied back into the client area after the window is sized or repositioned.

清除客户区的所有内容。如果未设置该标志,客户区的有效内容被保存并且在窗口尺寸更新和重定位后拷贝回客户区。

SWP_NOMOVE

0x0002

Retains the current position (ignores X and Y parameters).

维持当前位置(忽略X和Y参数)。

SWP_NOOWNERZORDER

0x0200

Does not change the owner window's position in the Z order.

不改变z序中的所有者窗口的位置。

SWP_NOREDRAW

0x0008

Does not redraw changes. If this flag is set, no repainting of any kind occurs. This applies to the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent window uncovered as a result of the window being moved. When this flag is set, the application must explicitly invalidate or redraw any parts of the window and parent window that need redrawing.

不重画改变的内容。如果设置了这个标志,则不发生任何重画动作。适用于客户区和非客户区(包括标题栏和滚动条)和任何由于窗回移动而露出的父窗口的所有部分。如果设置了这个标志,应用程序必须明确地使窗口无效并区重画窗口的任何部分和父窗口需要重画的部分。

SWP_NOREPOSITION

0x0200

Same as the SWP_NOOWNERZORDER flag.

与SWP_NOOWNERZORDER标志相同。

SWP_NOSENDCHANGING

0x0400

Prevents the window from receiving the WM_WINDOWPOSCHANGING message.

防止窗口接收WM_WINDOWPOSCHANGING消息。

SWP_NOSIZE

0x0001

Retains the current size (ignores the cx and cy parameters).

维持当前尺寸(忽略cx和Cy参数)。

SWP_NOZORDER

0x0004

Retains the current Z order (ignores the hWndInsertAfter parameter).

维持当前Z序(忽略hWndlnsertAfter参数)。

SWP_SHOWWINDOW

0x0040

Displays the window.

显示窗口。

 至此通过恢复主程序窗口时进行一下相应的刷新就能解决显示异常的问题,虽然工作做得比较草率,但本文重点是还是记录一下关于日常使用MFC窗口显示的一些Tips。方便与大家交流和日后自己回顾和完善修改。

 

参考文章:https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowpos

https://www.cnblogs.com/canger/p/5869173.html?utm_source=itdadao&utm_medium=referral

https://www.cnblogs.com/wb-DarkHorse/archive/2013/07/08/3178201.html 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值