GUI程序原理分析
文章目錄
- 1 命令行應用程序
- 2 圖形界面應用程序
- 3 GUI程序實例分析
- 3.1 GUI程序開發概述
- 3.2 基于面向過程的GUI程序開發實例
- 3.3 基于面向對象的GUI程序開發實例
- 3.4 QT的本質
1 命令行應用程序
命令行應用程序的特點(Command Line Interface):
- 是一種基于順序執行結構的可執行程序。
- 程序執行過程中不需要與用戶產生交互。
- 程序執行后會給出最終的運行結果。
比如:gcc a.c b.c c.c,編譯過程中不產生用戶交互,編譯結束后或者生成可執行程序或者給出錯誤信息。
命令行應用程序的運行模式:
命令行應用程序適用于:
- 單任務場合。
- 無交互或簡單交互場合。
- 服務器應用場合。
命令行應用程序是早期計算機系統中的主要程序類型。
2 圖形界面應用程序
圖形界面應用程序的誕生:
- 隨著計算機技術的發展,計算機走進日常生活。
- 計算機程序開始需要處理各個領域中的問題。
- 計算機用戶已經不再是專業的計算機工作者。
問題:如何讓計算機程序更好的適應普通用戶并走進日常生活?
圖形界面應用程序的特點(Graphic User Interface):
- 是一種基于消息驅動模型的可執行程序。
- 程序的執行依賴于用戶的交互過程。
- 程序執行過程中實時響應用戶操作。
- 一般情況下程序執行后不會主動退出。
圖形界面應用程序的運行模式:
圖形界面應用程序的消息處理模型:
圖形界面應用程序適用于:
- 多任務場合。
- 強用戶交互的場合。
- 非專業計算機用戶。
圖形界面應用程序是當代計算機系統中的主要程序類型。
當代大型軟件產品架構模型:
命令行應用程序和圖形界面應用程序的對比:
3 GUI程序實例分析
3.1 GUI程序開發概述
現代操作系統支持GUI界面:
- 現代操作系統提供原生SDK支持GUI程序開發。
- GUI程序開發是現代操作系統上的主流技術。
- 不同操作系統上的GUI開發原理相同。
- 不同操作系統上的GUI SDK不同。
GUI程序開發原理分析:
- GUI程序在運行時會創建一個消息隊列。
- 系統內核將用戶操作翻譯成對應的程序消息。
- 程序在運行過程中需要實時處理隊列中的消息。
- 當隊列中沒有消息時,程序處于停滯狀態。
不同操作系統支持相同的GUI開發原理:
GUI程序開發:
- 在代碼中用程序創建窗口及窗口元素
- 在消息處理函數中根據程序消息做出不同響應。
3.2 基于面向過程的GUI程序開發實例
多數操作系統以C函數的方式提供GUI SDK,以Windows操作系統為例:
使用win32進行GUI初體驗:
運行效果:生成主窗口,主窗口上添加一個按鈕,點擊后彈出對話框。
3.3 基于面向對象的GUI程序開發實例
GUI用戶界面是由固定的窗口元素所構成的:
對于操作系統來說:
- 操作系統系統了創建用戶界面元素所需要的函數。
- 各種功能不同的函數依次調用,從而創建出界面元素。
- 操作系統提供的原生函數無法直接映射到界面元素。
我們如何直觀的將界面元素的概念直接映射到程序中呢?
面向對象的GUI程序設計:
- GUI應用程序是為了解決非科學計算問題而誕生的。
- GUI應用程序適用于非專業的日常生活領域。
- 面向過程程序設計方法學不適合GUI程序設計。
- 面向對象程序設計方法學更適合GUI程序設計。
我們用另一種眼界看GUI開發:
- 用面向對象方法學看待GUI界面元素。
- 所有的界面元素都可以看作實際的對象。
- GUI用戶界面是由各不相同的對象組成的。
比如:
- 主窗口對象
- 菜單對象
- 按鈕對象
- 文本框對象
用面向對象的思想開發GUI應用程序,我們只需要考慮如下幾個問題:
- 主界面上有哪些界面元素?
- 這些類都已經支持了嗎?還是需要另外開發?
- 需要的界面元素都對應哪些類?
- 程序中需要幾個對話框?
GUI開發非常適合采用面向對象方法學:
- 將界面元素定義為對應的類。
- 通過抽象和封裝可以隱藏界面元素的細節。
- 程序的創建過程就是組合不同界面元素對象的過程。
接下來我們將上面基于面向過程的GUI程序修改為基于面向對象的GUI程序,但是未實現控件的消息映射部分。先看一下代碼的組織結構:
Application:
Widget:
// Widget.h #pragma once#include <windows.h>class Widget { protected:Widget* m_parent;HWND m_hwnd; public:Widget();Widget(Widget* parent);HWND hwnd();Widget* parent(); };// Widget.cppMainWindow:
// MainWindow.h:#pragma once#include "Widget.h"class MainWindow : public Widget { protected:static const wchar_t STYLE_NAME[];/* 主窗口定義函數 */BOOL defineMainWindow(HINSTANCE hInstance);/* 主窗口創建函數 */void createMainWindow(HINSTANCE hInstance, const wchar_t* title);/* 主窗口消息處理函數 */static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); public:MainWindow(HINSTANCE hInstance, const wchar_t* title);void show(); };// MainWindow.cpp:#include "MainWindow.h"const wchar_t MainWindow::STYLE_NAME[] = L"MainForm";MainWindow::MainWindow(HINSTANCE hInstance, const wchar_t* title) : Widget(NULL) {defineMainWindow(hInstance);createMainWindow(hInstance, title); }void MainWindow::show() {ShowWindow(m_hwnd, SW_SHOWNORMAL); // 顯示窗口UpdateWindow(m_hwnd); // 刷新窗口 }BOOL MainWindow::defineMainWindow(HINSTANCE hInstance) {static WNDCLASS WndClass = {0}; // 系統結構體類型// 用于描述窗口樣式WndClass.style = 0;WndClass.cbClsExtra = 0;WndClass.cbClsExtra = 0;WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW); // 定義窗口背景色WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); // 定義鼠標樣式WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 定義窗口左上角圖標WndClass.hInstance = hInstance; // 定義窗口式樣屬于當前應用程序WndClass.lpfnWndProc = WndProc; // 窗口消息處理函數WndClass.lpszClassName = STYLE_NAME; // 窗口樣式名WndClass.lpszMenuName = NULL;/* 將定義好的窗口式樣注冊到系統 */return RegisterClass(&WndClass); }void MainWindow::createMainWindow(HINSTANCE hInstance, const wchar_t* title) {m_hwnd = CreateWindow(STYLE_NAME, // 通過定義好的窗口式樣創建主窗口title, // 主窗口標題WS_OVERLAPPEDWINDOW, // 創建后主窗口的顯示風格CW_USEDEFAULT, // 主窗口左上角 x 坐標CW_USEDEFAULT, // 主窗口左上角 y 坐標CW_USEDEFAULT, // 主窗口寬度CW_USEDEFAULT, // 主窗口高度NULL, // 父窗口NULL, // 窗口菜單欄hInstance, // 主窗口屬于當前應用程序NULL); // 窗口參數 }LRESULT CALLBACK MainWindow::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {switch(message){case WM_DESTROY:PostQuitMessage(0);break;}/* 調用系統提供的默認消息處理函數 */return DefWindowProc(hwnd, message, wParam, lParam); }PushButton:
// PushButt.h #pragma once#include "Widget.h"class PushButton : public Widget { public:PushButton(Widget* win, const wchar_t* text); };// PushButt.cpp#include "PushButton.h"PushButton::PushButton(Widget* win, const wchar_t* text) {HINSTANCE hInstance = (HINSTANCE)GetWindowLong(win->hwnd(), GWL_HINSTANCE);m_hwnd = CreateWindow(L"button", // 通過系統預定義式樣創建窗口元素text, // 窗口元素標題WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, // 窗口元素的顯示風格50, // 窗口元素在窗口中的左上角 x 坐標50, // 窗口元素在窗口中的左上角 y 坐標200, // 窗口元素的寬度60, // 窗口元素的高度win->hwnd(), // 窗口元素所在的父窗口(HMENU)this, // 窗口元素 ID 值hInstance, // 窗口元素屬于當前應用程序NULL); // 窗口元素參數 }main
// main.cpp #include <windows.h> #include "Application.h" #include "MainWindow.h" #include "PushButton.h"BOOL WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {Application a(hInstance, lpCmdLine);MainWindow w(hInstance, L"Main Window");PushButton b(&w, L"My Button");w.show();return a.exec(); }3.4 QT的本質
對于QT:
- QT是利用面向對象方法學開發的一套GUI組件庫。
- QT將不同操作系統的GUI細節封裝于類的內部,具有跨平臺的特性。
- QT提供一套跨平臺的類用于開發GUI程序。
- QT遵循經典的GUI應用程序開發模式。
- QT是一套跨平臺的GUI開發庫。
- QT是一套C++集成開發環境。
- QT是一套開源的殿堂級架構技術教程。
參考資料:
總結