图形用户界面若干基础疑问

自研GUI框架解析

来来来,挖坑挖坑,思来想去,先把这个坑填掉,不深入研究,只求解惑。–2020年4月29日 11点43分

一直有几个问题,在若干年前就开始疑惑了:

  1. 这些图形界面库是怎么画出来的?
  • Win32\WTL\ATL\MFC\

  • Qt\wxWidgets\FLTK\Nana\

  • WinForms\WPF\

  • DirectUI\Duilib\

  • SWing\

  • tkinter\

    windows平台下都调用了win32接口,只是封装了起来而已。

    Win32窗口机制,是windows一系列图形界面的基石。无论你是MFC一层薄薄的封装,还是QT等第三方工具,都是基于对Win32一系列 API的调用。CreateWindow之后,一个基于HWND句柄的空白窗口出现你眼前。虽然此时你什么也不做,但Win32窗口依然不间断的收到各种类型的窗口消息。在这一系列消息中,WM_PAINT消息至关重要,它决定了你程序的最终UI界面。PANIT消息是一个数据结构,提供了绘图关键的HDC设备上下文接口。
    作者:网络芝麻
    链接:https://www.zhihu.com/question/56870169/answer/150731083
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  1. 项目的实际需求中,只涉及到很少的功能,大部分界面库太厚重了,没用的东西太多,怎样才能做到符合实际需求?

    回到题目上,为什么不用QT/MFC?从专业性上来讲因为公司有实力和资源自主开发一个框架,这样可以不受制于人,并且根据自身业务特点对框架进行针对性的定制和性能优化,而且这也是大公司非常专业的做法。Client开发不像后台开发有很多可靠的开源解决方案,所以造轮子是十分必要的,而且可以造出来比市面上更好的轮子。为什么公司喜欢造轮子,因为造轮子才显得专业:
    作者:tishion
    链接:https://www.zhihu.com/question/67320946/answer/253059396
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  2. 目前的跨平台库都是以兼容各大平台的接口实现的。那么windows平台下,是否可以摆脱win32 API?

    理论上不可以。除非突破平台限制,直接与硬件驱动对话。

  3. 是否可以自定义实现一个简单的界面?

    可以,但它喵的需要时间,连环嵌套坑。这坑基本就等同于windows平台下的win32SDK开发。别想乱七八糟了,反正都是win32的封装。

    如果想开发界面程序,并且有能够深入理解Windows的机制,特别建议用WTL,WTL是微软ATL的那些人开放的一个WindowsGUI程序开发的模板库,无论是迅雷的Blot还是金山的界面库,还有腾讯的界面库,基本上都是在WTL的基础上搭建起来的,WTL解决了一个重要问题,Win32窗口类必须是全局函数,所以用类封装的时候,必须用一些取巧的机制才能顺利的封装窗口类,并且又不失效率,而WTL的thunk机制非常先进,成功的解决了这个问题。在追求效率和开发速度,WTL都做的不错,模板技术的使用使得编译后体积和运行速度远远优于MFC,C#没有Native的时候,WPF开发的程序一旦体积巨大,问题就会暴露出来。Qt,在Windows上体积太大,信号和槽的机制和Windows消息机制存在一定的差异,封装过程的代价还未可知。所以个人看法建议使用WTL,唯一不足是WTL并没有得道官方的正式支持,但代码依然在更新,最近增加了Nuget的支持。
    作者:Charlie
    链接:https://www.zhihu.com/question/24461881/answer/28646451
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  4. ​tcl/tk中tkinter是怎么运作的?:
    ​tcl/tk:http://www.tcl.tk/
    惭愧,这个问题暂时无法回答,下次来放答案吧(可能没下次了 )。这简直是个轮回,上次关注tcl是在2010年。my god。

  5. ​vtk中的win32窗口从哪里来?
    之前专门找过VTK中的窗口创建,详细说明请移步这里:vtk中的win32窗口

  6. ​如何自己封装一套界面库?
    网上的轮子很多了,借过来学习一下是非常值得的,前提是要合理安排时间。
    Win32++:http://win32-framework.sourceforge.net/
    Gaclib:http://www.gaclib.net/

本文不会扩展太大的范围,旨在学习windows绘制窗口的原理,只要自己能回答上面几个问题即可,点到为止。

唉,gui的本质就是一个死循环,根本不存在,万物皆假象,这个时候还提什么gui,会用哪个用哪个罢了!最后给出一个简单的类,假装自己动过手。
win32gui.h

#pragma once

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib,"winmm.lib")
#define WINCLASSNAME "win32gui" //应用程序名称
LRESULT WINAPI WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ); //声明窗口函数

class win32gui
{
public:
	win32gui(void);
	~win32gui(void);

	bool RegWnd(UINT Icon=0,UINT cur=0);//注册窗口
	bool CreateWnd(LPCTSTR title,HINSTANCE PrevInst,bool isFull);//创建窗口
	bool Run();//消息循环
	void DeleteWnd();//结束应用程序
private:
	WNDCLASSEX wc;
	MSG m_msg;
	int m_width;
	int m_height;
	HWND m_hWnd;

	HINSTANCE hInstance;
};

win32gui.cpp

#include "win32gui.h"

win32gui::win32gui(void)
{
	hInstance = GetModuleHandle(NULL);//获取实例句柄
}
win32gui::~win32gui(void)
{
}
//-----------------------------------------------------------------------
//注册窗口
//----------------------------------------------------------------------
bool win32gui::RegWnd(UINT Icon,UINT cur)
{
	// 定义一个Windows类,指定消息的处理函数为MsgProc
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = wc.cbWndExtra = NULL;
	wc.hInstance = hInstance;
	wc.hbrBackground = (HBRUSH)GetStockObject(COLOR_WINDOW+1);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = TEXT("win32gui");
	wc.hIcon = wc.hIconSm = LoadIcon(NULL,IDI_APPLICATION); 
	wc.hCursor = LoadCursor(NULL,IDC_ARROW); 
	if(cur)  
		wc.hCursor=LoadCursor(NULL,IDC_ARROW);     //定义鼠标图标 
	// 注册这个窗口类
	RegisterClassEx( &wc );
	return true;
}
//-------------------------------------------------------------------------------------------
//创建窗口
//-------------------------------------------------------------------------------------------
bool win32gui::CreateWnd(LPCTSTR title,HINSTANCE PrevInst,bool isFull)
{
	if(PrevInst) 
		return false;                  //判断是否已经有相同的应用实体在运行

	// 创建应用程序窗口
	m_hWnd = CreateWindowEx(NULL,
							wc.lpszClassName,
							wc.lpszClassName,
							WS_OVERLAPPEDWINDOW,
							CW_USEDEFAULT,
							CW_USEDEFAULT,
							CW_USEDEFAULT,
							CW_USEDEFAULT,
							NULL,
							NULL,
							wc.hInstance,
							NULL );//创建窗口

	if(!m_hWnd)  
		return false; 
	// 显示窗口
	ShowWindow( m_hWnd, SW_SHOW );
	UpdateWindow( m_hWnd );
	return true;
}
//----------------------------------------------------------------------------------------------
//运行,消息循环
//----------------------------------------------------------------------------------------------
bool win32gui::Run()
{      
	if( m_msg.message != WM_QUIT)
	{
		////进入消息循环
		while(true)
		{
			if(!GetMessage(&m_msg,0,0,0))
				break;
			TranslateMessage(&m_msg);
			DispatchMessage(&m_msg);
		}
		return true;
	}
	else 
		return false; 
}
//-------------------------------------------------------------------------------
// 注销窗口类
//--------------------------------------------------------------------------------
void win32gui::DeleteWnd()
{ 
     UnregisterClass(TEXT("win32gui"), wc.hInstance );
}
//窗口过程回调函数,在这里处理窗口消息
LRESULT WINAPI WndProc( HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
	switch(uMsg)
	{
	case WM_DESTROY:
		PostQuitMessage(NULL);
		break;
	}
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

main.cpp:

#include "win32gui.h"
int main()
{
	win32gui *m_gui = new win32gui;
	m_gui->RegWnd();
	m_gui->CreateWnd(TEXT("win32gui"),0,0);
	m_gui->Run();
	return 0;
}

参考文献

  1. 腾讯QQ为什要自研UI框架,而不用QT/MFC? - 知乎
    https://www.zhihu.com/question/67320946/answer/253059396
  2. Gaclib – GPU Accelerated C++ User Interface (vczh)
    http://www.gaclib.net/
  3. win32窗口创建之通俗易懂版_运维_DGDDHDHDH的博客-优快云博客
  4. Win32++:http://win32-framework.sourceforge.net/
  5. Nana C++ Library - a modern C++ GUI library:http://nanapro.org/en-us/
根据您提供的文档内容,我将为您详细解释数织游戏的实现要求及相关注意事项。以下是针对这份文档内容的整理与解析: ### 游戏背景及规则 - **游戏名称**:数织游戏(MagicBall) - **游戏界面**:基于命令行的伪图形界面,支持鼠标交互。 - **游戏逻辑**:在一个矩形区域内随机分布若干个球,并通过行列提示帮助玩家猜测球的位置。 ### 实现要求概述 #### 环境准备 - 使用Visual Studio 2022作为开发环境。 - 必须关闭命令行窗口的“快速编辑模式”和“插入模式”,确保支持鼠标事件。 - 提供了`cmd_console_tools.cpp`和`.h`文件用于构建伪图形界面,这两个文件不可修改。 #### 编程限制 - 不允许使用`scanf/printf`进行I/O操作。 - 禁止使用全局变量(const常量除外)。 - 禁止使用黑名单中的知识点(详情参见520加分活动)。 #### 功能模块划分 文档将整个游戏开发任务划分为多个子任务(A~K),逐步增加难度,确保学生能够循序渐进地掌握相关技能。这些子任务涵盖了从基础的矩阵初始化到完整的带有分隔线的图形界面游戏实现。 ### 子任务解析 1. **子任务 A**:实现矩阵初始化与基本展示。 - 用户输入矩阵尺寸,并验证输入合法性。 - 初始化并打印空白矩阵,使用字母标识行列。 2. **子任务 B**:添加行列提示信息。 - 根据球的数量生成正确的行提示和列提示,并正确排版。 3. **子任务 C**:基于文本界面的简单游戏操作。 - 用户可以通过键盘输入坐标来标记球的存在与否。 4. **子任务 D**:创建简单的伪图形界面。 - 包括绘制外围框线,并根据屏幕尺寸调整字体大小。 5. **子任务 E**:增强版伪图形界面,加入行列提示。 - 在子任务D的基础上增加了提示栏。 6. **子任务 F**:引入鼠标支持,实现实时坐标反馈。 - 当鼠标悬停在有效区域内时,显示当前坐标;点击有效区域内的某点后结束程序。 7. **子任务 G**:完整的游戏流程。 - 实现提交答案、检查结果以及退出游戏等功能。 8. **子任务 H**:带有分隔线的伪图形界面。 - 对比子任务D,增加了球之间的分隔线。 9. **子任务 I**:结合分隔线与提示栏的界面。 - 基于子任务H,进一步整合提示栏。 10. **子任务 J**:带有分隔线的完整游戏体验。 - 完善鼠标交互功能,保证用户体验流畅。 11. **子任务 K**:最终版本——支持分隔线的完整游戏。 - 综合前几项任务的优点,提供最完善的游戏体验。 ### 注意事项 - 所有提交的源文件应放置在同一项目和同一目录下,以避免编译错误。 - 确保代码符合编码规范,特别是避免使用过多的if-else或switch-case语句来处理类似情况。 - 虽然对于内部数组的数据类型、字体样式等方面没有严格规定,但必须保证程序在1920x1080分辨率下正常运行。 ### 知识点 1. **伪图形界面编程** - 使用特定API绘制图形元素,模拟图形界面效果。 2. **鼠标事件处理** - 捕获并响应鼠标的移动、点击等动作,提升交互性。 3. **动态内存管理** - 根据用户输入动态分配内存,构建适应不同大小的游戏区域。 以上是对这份文档内容的理解与总结,希望能够帮助您更好地理解和规划数织游戏的开发工作。如果有任何疑问或其他需求,请随时告知。
最新发布
06-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值