GUI框架如何工作?

Ale*_*.B. 7 graphics user-interface frameworks

我一直在网上寻找答案,我的问题是:GUI框架如何工作?例如,Qt是如何工作的,是否有关于从头开始编写GUI框架主题的书籍或wibsites?并且框架还必须从操作系统GUI框架调用方法吗?

- 感谢任何一个花时间尝试回答这个问题的人,如果我拼错了任何东西,请原谅我.

cHa*_*Hao 5

像Qt这样的GUI框架通常可以通过获取现有操作系统的原始对象(窗口,字体,位图等),将它们包含在更加平台中立且不那么笨重的类/结构/句柄中,并为您提供所需的功能.操纵它们.是的,这几乎总是涉及使用操作系统自己的功能,但它没有 - 如果你正在设计一个API来绘制OpenGL UI,例如,大多数底​​层操作系统的GUI内容都无法工作,你将自己做几乎所有的事情.

无论哪种方式,它都不适合胆小的人.如果你不得不问一下GUI框架是如何工作的,你甚至还没准备好设计它.你最好坚持使用现有的框架并扩展它来做它已经没有做过的漂亮的东西.


小智 5

在过去,我们从头开始进行许多GUI编程。这虽然看起来并不困难,但要花几周的时间才能得出结果。

首先,您需要一个好的图纸库。该库的最小功能是绘制剪切的矩形(使用图案),线条,位图和字体。您可以通过将字体创建为位图来作弊,并且被裁剪的矩形只是一堆水平线。

现在,您至少需要鼠标,键盘和计时器的驱动程序(如果操作系统尚未提供)。通常,您将需要检测键,符号键(例如Shift等),鼠标移动和鼠标单击。基本的计时器功能可让您检测双击。

然后,您需要创建一个窗口数据结构。该数据结构需要具有坐标(即矩形),链接到父窗口(如果不是顶部窗口)和窗口函数(即当该窗口应处理某些事件时将要调用的函数)的坐标。

一旦可以在屏幕上绘制,就需要一些矩形代数函数。您至少需要一个好的函数来计算矩形的交点,并需要相对于绝对坐标的快速分辨率。例如-如果您的子窗口有父窗口,则应将其x和y递归添加到父x和y,直到到达顶部窗口。

此时,您将拥有:-原始图形功能-窗口结构-鼠标驱动程序,键盘驱动程序和计时器-矩形算术

现在,您可以编写主事件收集功能。此功能将一直运行。目的是检测事件并向正确的窗口发送消息。什么事 好了,当您启动程序时,请存储鼠标的x和y坐标。然后循环检查它们是否已更改。如果它们已更改,请在该位置找到窗口...并向其发送WM_MOUSEMOVE事件。您的收割功能应处理:-鼠标移动-鼠标单击-鼠标双击(记住最后单击和位置,测量时间并确定是否是双击)-计时器事件-键盘缓冲区更改...

现在您应该能够将事件发送到Windows。但是您确实需要一种机制。它是消息队列和窗口过程的组合。通常它是这样工作的:每个窗口都有一个窗口过程,该过程通常接受四个参数:消息ID(即鼠标移动,是否绘制消息),窗口句柄,参数1和参数2。您可以直接使用调用此窗口过程类似于send_message函数。或者,您可以通过post_message函数向该窗口发送消息。这会将消息放入队列,窗口将一个接一个地处理消息,最终接收到该消息。那么,为什么要直接调用一条消息,然后将其他消息放入队列呢?因为优先。您会看到,键盘单击可能需要一段时间才能被处理。但是窗口重绘必须立即完成,以防止闪烁和屏幕上的错误数据。

因此,您的Harvest_events函数使用post_message和send_message将消息发送到Windows。您的窗口消息泵使用典型的消息泵来获取它们,如下所示:

while(pmsg = get_message()!= NULL)send_message(pmsg-> id,pmsg-> hwnd,pmsg-> p1,pmsg-> p2);

get_message只是从队列中获取消息,然后调用发送消息。简单吧?好吧,事实并非如此。这样,您将只收到发送到窗口的驱动程序消息,但是您还需要一些函数来重绘窗口移动窗口等。当您创建move_window函数,resize_window,show_window和hide_window函数时,窗口坐标将发生变化。其他窗口的部分将被发现(如果顶部窗口被移动或关闭)。您需要计算哪些窗口受坐标更改的影响,并向这些窗口发送绘制消息(仅重新绘制那些被发现的部分-请记住,您已经裁剪了绘图功能,这样就可以使用)。

这些功能介绍了消息msg_paint,msg_move,msg_resize,msg_hide ...

最后,您需要维护Windows的层次结构。您的顶部窗口应该是桌面。它应该具有子窗口(应用程序顶部窗口)。这些窗口可能还有其他子窗口(按钮,编辑框等)。保留这些窗口的明显结构是窗口树。当检测到鼠标单击时,您必须遍历窗口树并以一种聪明的方式(找出谁有焦点,谁是模态的,等等)进行操作,以将消息发送到右侧窗口。当您画画时,您还必须遍历所有孩子,看看谁被发现,谁未被发现。最后但并非最不重要的一点是,您需要将鼠标矩形作为顶部窗口处理,以防止在重新绘制窗口或(使用计时器和msg_paint事件)动画时使鼠标闪烁。

大概就是这样。

  • IMO,这个答案和评论应该是公认的答案。 (3认同)
  • 有谁知道一本涵盖 3 种或更多构建和实际 GUI 框架设计方法的教科书,而不仅仅是作为 api 用户? (2认同)