整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          VC|窗口對象句柄、指針、ID的獲取及它們之間的轉換

          VC|窗口對象句柄、指針、ID的獲取及它們之間的轉換

          DK的WIN32 API用句柄HANDLE操作Windows窗口,而VC將HANDLE封裝為CWnd類的一個成員變量m_hWnd,可以取此對象的m_hWnd屬性來得到句柄。同時,VC中每一個窗口類都可以聲明為一個窗口指針來調用窗口類的成員屬性和成員變量。

          1 窗口

          窗口是Windows應用程序中一個非常重要的元素,一個Windows應用程序至少要有一個窗口,稱為主窗口,窗口是指現在是屏幕上面的一快矩形區域,是Windows應用程序與用戶進行交互的接口。利用窗口,可以接收用戶的輸入及顯示輸出。

          一個應用程序窗口通常包含標題欄、菜單欄、系統菜單、最小化框、最大化框、可調邊框、滾動條等

          窗口可以分為客戶區和非客戶區,客戶區是窗口的一部分,應用程序通常在客戶區中顯示文字或繪制圖形。而標題欄、菜單欄、系統菜單、最小化和最大化,可調系統邊框為窗口的非客戶區,他們由windows來管理,而應用程序則主要管理客戶區的外觀及操作。

          窗口可以有一個父窗口,有父窗口的窗口稱為子窗口,另外,對話框和消息框也是一種窗口,在對話框上面還包含許多子窗口,這些子窗口的形式有按鈕、單選按鈕、復選框、組框、文本編輯框等。

          此外,在我們啟動Windows系統后,我們的桌面也是一個窗口,稱為桌面窗口,是位于最上層的窗口,由Windows系統創建和管理。

          2 窗口句柄

          當用你CreateWindow創建了一個窗口,這個窗口其實并不是你創建的,而是系統替你的創建的,系統為創建這個窗口,它必須要保留很多的和這個窗口相關的數據,這些數據并不是給你用的,而是系統用來維護窗口用的,而句柄就是系統用來找到這個窗口相關數據的一人索引。你向一個API提供一個句柄,比如ShowWindow(HWND);要顯示這個窗口,這個工作還是系統替你做的,它根據你提供的索引,也就是句柄,找到窗口,然后進行相關的處理。所以說,句柄是相關對象的唯一索引。從這一點上看,有點像指針,但是指針的內容是對象的地址,而句柄并不是地址,句柄只是一個索引,一個整數。

          句柄的實質就是一個結構體的實例。

          Windows系統中有許多內核對象(這里的對象不完全等價于"面向對象程序設計"一詞中的"對象",雖然實質上還真差不多),比如打開的文件,創建的線程,程序的窗口,等等。這些重要的對象肯定不是4個字節或者8個字節足以完全描述的,他們擁有大量的屬性。為了保存這樣一個"對象"的狀態,往往需要上百甚至上千字節的內存空間,那么怎么在程序間或程序內部的子過程(函數)之間傳遞這些數據呢?拖著這成百上千的字節拷貝來拷貝去嗎?顯然會浪費效率。那么怎么辦?當然傳遞這些對象的首地址是一個辦法,但這至少有兩個缺點:

          I 暴露了內核對象本身,使得程序(而不是操作系統內核)也可以任意地修改對象地內部狀態(首地址都知道了,還有什么不能改的?),這顯然是操作系統內核所不允許的;

          II 操作系統有定期整理內存的責任,如果一些內存整理過一次后,對象被搬走了怎么辦?

          所以,Windows操作系統就采用進一步的間接:在進程的地址空間中設一張表,表里頭專門保存一些編號和由這個編號對應一個地址,而由那個地址去引用實際的對象,這個編號跟那個地址在數值上沒有任何規律性的聯系,純粹是個映射而已。

          在Windows系統中,這個編號就叫做"句柄"。

          在Windows應用程序中,窗口是通過句柄HWND來標識的,我們要對某個窗口進行操作,首先就要獲取到這個窗口的句柄。

          每個窗口在被創建出來之后就會被賦予一個句柄,該句柄指向一個數據結構體,結構體里明確表示著該窗口的各種信息,窗口大小,窗口名等,當我們得到這個句柄時就可以請求操作系統對它做一系列操作,列如:移動窗口,關閉窗口,最小化最大化等,這些都是通過窗口句柄來告訴操作系統的,我們要對哪個窗口進行操作,而消息則是告訴操作系統要做什么樣的操作,消息的附加參數就是操作值,列如移動窗口,會有附加的xy坐標參數!

          句柄有Windows句柄,文件句柄,分配內存句柄,圖形句柄等,系統在創建這次資源的時候回為其分配內存,并返回標識這些資源的標識號,這個標識號就是句柄,實際上,我們可以將句柄看做是指針。

          在使用句柄之前,必須先創建他們,當不在使用時,應當及時銷毀,如果不銷毀他們,最終將到時資源泄露,資源泄露有可能導致系統崩潰,所以,務必確保在適當的時候銷毀不在使用的句柄。

          另外,程序運行時也是以進程存在,進程也是用ID或句柄去標識。

          進程創建時,windows系統為進程構造了一個句柄表。當該進程希望獲得一個內核對象句柄或者創建一個內核對象從而獲得該對象句柄時。系統會將在句柄表中增加一個表項,表項的內容中存儲了指向目標內核對象的指針。同時,系統返回這個表項在句柄表中的索引作為句柄。這樣,進程就通過句柄查詢句柄表得到對象指針,從而可以訪問該對象。同時又由于有了句柄表的保護,可以防止對內核對象的非法操作。

          3 Windows對象和MFC對象的區別

          windows對象并不是我們平時所說的“面向對象”程序設計中的“類的對象”,而是一種windows資源實體,如畫筆、字體等。

          如果想要去使用這些windows對象我們需要用句柄來標識它們。

          而MFC對象則是真正的“面向對象”思想中的“類的對象”(必須用構造函數去創建)。

          在windows編程中,除了普通的“類的對象”外,用得最多的“C++類的對象”應該是MFC對象了(如果你是用MFC編程的話),

          MFC對象是指“封裝了windows對象的C++對象”(也就是MFC對象中有一個控制window對象的控制器,那么控制器想工作就得和一個window對象鏈接起來,這樣就能控制器就能控制這個對象了)。

          所謂Windows對象是Win32下用句柄表示的Windows操作系統對象;

          所謂MFC對象就是C++對象,是一個C++類的實例.

          一個MFC窗口對象是一個C++ CWnd類(或派生類)的實例,是程序直接創建的。

          在程序執行中它隨著窗口類構造函數的調用而生成,隨著析構函數的調用而消失。

          而Windows窗口則是Windows系統的一個內部數據結構的實例,由一個“窗口句柄”標識,Windows系統創建它并給它分配系統資源。

          Windows窗口在MFC窗口對象創建之后,由CWnd類的Create成員函數創建,“窗口句柄”保存在MFC窗口對象的m_hWnd成員變量中。

          Windows窗口可以被一個程序銷毀,也可以被用戶的動作銷毀。

          MFC中的窗口類,就是C++類與Windows窗口的句柄的結合。在基于CWnd繼承而來的所有類中,都有一個公有的成員變量m_hWnd,這個成員變量就是窗口對象關聯的windows窗口句柄。我們在類中可以直接使用這個窗口句柄成員變量。這個窗口對象就是標準的C++對象。其實MFC窗口類并不神奇,就是包裝了一下API而已。m_hWnd的類型就是HWND。MFC給CWnd提供了兩個成員函數Attach(HWND hWndNew )和Detach()。前者傳入一個窗口句柄,將該窗口關聯到C++對象,后者則是將當前關聯的窗口解關聯。而關聯就是給m_hWnd賦值,解關聯就是將m_hWnd設置為NULL。解關聯后,窗口對象就不關聯任何窗口了,此時就不能執行窗口相關的任何操作,都會失敗。如果要關聯新的窗口,只要執行Attach函數即可。

          4 對話框控件消息響應函數中可以直接調用的函數

          4.1 MFC全局函數,如:

          AfxMessageBox 顯示一個消息框

          AfxGetApp 返回應用程序對象CWinApp的一個指針

          AfxGetAppName 返回應用程序的名稱

          AfxInitRichEdit 為應用程序初始化RichEdit控件

          4.2 API函數,如:

          SendMessage(),調用一個窗口的窗口函數,將一條消息發給那個窗口;

          OpenFile() 這個函數能執行大量不同的文件操作;

          RegCreateKey() 在指定的項下創建或打開一個項;

          GetCaretPos() 判斷插入符的當前位置;

          ShellExecute() 用指定程序打開指定路徑下的文件;

          4.3 其父類定義的成員函數,如CWnd類:

          PreSubclassWindow()

          在調用SubclassWindow之前,允許其它必要的子類化工作

          FromHandle()

          當給定一個窗口的句柄時,返回CWnd對象的指針。如果沒有CWnd對象與這個句柄相連接,則創建一個臨時的CWnd對象并與之相連接

          GetSafeHwnd

          返回m_hWnd,如果該指針為NULL,則返回NULL

          etFocus()

          要求輸入焦點

          SetWindowPos()

          改變子窗口、彈出窗口和頂層窗口的大小、位置以及順序

          GetClientRect

          獲得CWnd客戶區域的大小

          GetDlgItem(),

          獲得指定的對話框中具有指定ID的控件

          UpdateData()

          初始化對話框或獲得對話框中的數據

          SetWindowText()

          將窗口的文本或標題文字(如果有)設為指定的文本

          SetWindowText

          將窗口的文本或標題文字(如果有)設為指定的文本

          SetTimer()

          安裝一個系統定時器,當它被激活時,發送一個WM_TIMER消息

          MessageBox()

          創建并顯示一個窗口,其中包含了應用程序提供的消息和標題

          SendMessage()

          向CWnd對象發送一個消息,直到這條消息被處理之后才返回

          OnPaint()

          調用這個函數以重畫窗口的一部分

          OnLButtonDown()

          當用戶按下鼠標左鍵時調用這個函數

          OnTimer()

          當達到SetTimer指定的時間間隔時調用這個函數

          4.4 繼承關系不同的GetDlgItem()

          1) CWindow::GetDlgItem
          HWND GetDlgItem(int nID)const;
          2) CWnd::GetDlgItem
          CWnd* GetDlgItem(int nID) const;
          void CWnd::GetDlgItem( int nID, HWND *phWnd) const;
          3)Windows SDK
          HWND GetDlgItem(HWND hDlg,int nIDDlgItem);
          

          5 窗口句柄和指針使用的場合

          先看下面的兩行代碼,簡單了解一下窗口句柄和指針的一個使用場合:

          5.1 API函數以句柄為參數

          CString str="在編輯框上顯示給定文本。";
          SendMessage(GetActiveWindow()->GetDlgItem(IDC_textbox)->m_hWnd, WM_SETTEXT , 0 , (LPARAM)str.GetBuffer(0));
          

          此代碼可以在當前活動窗口的IDC_textbox文本框控件中顯示一個字符串str。

          ① API函數SendMessage()功能:將指定的消息發送到一個或多個窗口。

          LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam)

          hWnd:其窗口程序將接收消息的窗口的句柄。如果此參數為HWND_BROADCAST,則消息將被發送到系統中所有頂層窗口,包括無效或不可見的非自身擁有的窗口、被覆蓋的窗口和彈出式窗口,但消息不被發送到子窗口。

          Msg:指定被發送的消息。

          wParam:指定附加的消息特定信息。

          IParam:指定附加的消息特定信息。

          返回值:指定消息處理的結果,依賴于所發送的消息。

          ② CWnd類方法GetDlgItem(IDC_textbox),能夠返回一個MFC指針*CWnd;

          ③ CWnd類方法GetActiveWindow(),可以返回當前窗口的一個HWND句柄;

          ④ “->m_hWnd”是將一個指針轉換為句柄。一般窗口對象都會有一個其對應的句柄變量,所以我們可以取此對象的m_hWnd屬性來得到句柄。

          5.2 MFC對象指針調用成員函數

          下面的的代碼也是在編輯框上顯示給定文件:

          CString str="在編輯框上顯示給定文本。";
          CEdit *edit1=(CEdit*)GetDlgItem(IDC_EDIT2);
          edit1->SetWindowText(str);
          

          GetDlgItem()可以返回一個MFC指針*CWnd,并用(CEdit*)做了下類型轉換,然后就可以使用CEdit類的成員函數,例如SetWindowText()。

          5.3 API函數使用句柄作為參數

          CString str="F:\\help\\list.html";
          API函數ShellExecute(this->m_hWnd, "open", str,"", NULL, SW_SHOW);	
          

          this->m_hWnd; //返回的就是窗口類自己的句柄呢,也可以用MFC全局函數:

          AfxGetMainWnd()->m_hWnd;

          6 窗口ID和指針

          對MFC編程來說,對話框和控件都可以理解為一個子窗口,都有對應的一個ID和類??梢苑祷貙膶ο笾羔?。

          7 獲得窗口句柄的方法

          HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName)

          HWND FindWindowEx(HWND hwndParent, HWND hwndChildAfter,LPCTSTR lpClassName, LPCTSTR lpWindowName)

          HWND WindowFromPoint(POINT& Point)//獲得當前鼠標光標位置的窗口HWND

          在任何類中獲得應用程序類

          HWND AfxGetInstanceHandle()

          獲取當前活動窗口句柄

          HWND GetActiveWindow(VOID)

          獲取前臺窗口句柄

          HWND GetForegroundWindow(void);

          獲得對話框中某控件的句柄

          HWND GetDlgItem(m_hDLG,m_nID_DlgItem);

          獲得GDI對象的句柄

          HWND m_hGDIObj=m_pGDIObj->GetSafeHanle();

          8 獲取窗口指針的辦法

          ① 獲取當前應用進程的指針

          AfxGetApp();

          ② 獲得主框架窗口指針(任何時候都可以用,只要是MFC程序中)

          CWnd* pWnd=AfxGetMainWnd();

          ③ 獲得對話框中控件指針

          CWnd* pWnd=GetDlgItem(IDC_xxx);

          可以強制轉換為具體類型,如CEdit *edit1=(*CEdit)GetDlgItem(IDC_xxx);

          ④ 獲得工具欄指針

          CToolBar * pToolBar=(CtoolBar*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);

          9 窗口、控件的指針和句柄的相互轉化

          ① 指針轉化為句柄

          在MFC應用程序中首先要獲得窗口的指針,然后將其轉化為句柄

          CWnd *pwnd=FindWindow(“ExploreWClass”,NULL); //希望找到資源管理器
          HWND hwnd=pwnd->m_hwnd; //得到它的HWND
          

          這樣的代碼當開始得到的pwnd為空的時候就會出現一個“General protection error”,并關閉應用程序,因為一般不能對一個NULL指針訪問其成員,如果用下面的代碼:

          CWnd *pwnd=FindWindow(“ExploreWClass”,NULL); //希望找到資源管理器
          HWND hwnd=pwnd->GetSafeHwnd(); //得到它的HWND
          

          就不會出現問題,因為盡管當pwnd是NULL時,GetSafeHwnd仍然可以用,只是返回NULL

          ② 句柄轉化為指針

          在MFC應用程序中首先用GetDlgItem()獲得對話框控件的句柄,然后獲得其指針:

          HANDLE hWnd;
          GetDlgItem(IDC_xxx,&hWnd);
          CWnd *pWnd=CWnd::FromHandle(hWnd);
          pWnd->Attach(hWnd); //Attaches a Windows to a CWnd object
          

          // 用FindWindow()得到一個窗口句柄,然后轉換為容器指針

          HWND hWnd=::FindWindow(NULL,_T("IDD_Assistants")); //得到對話框的句柄
          CAssistantsDialog* pWnd=(CAssistantsDialog*)CAssistantsDialog::FromHandle(hWnd); //由句柄得到對話框的對象指針
          pWnd- >xxx( ); //調用C***Dialog中的函數xxx();
          

          10 窗口、控件的指針和句柄與其ID的相互轉化

          ID->句柄,hWnd=::GetDlgItem(hParentWnd,id);

          ID->指針,CWnd::GetDlgItem();

          句柄->ID,id=GetWindowLong(hWnd,GWL_ID);

          指針->ID,id=GetWindowLong(pWnd->GetSafeHwnd,GWL_ID);

          HICON->ID,HICON hIcon=AfxGetApp()->LoadIcon(nIconID);

          ID->HICON,HICON hIcon=LoadIcon(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(nIconID));

          -End-

          當下,構建交互式應用程序的主流技術是 Web 技術,其中包括 HTML、CSS 與 JavaScript。

          在過去的 10 年,Web 技術生態發生了翻天覆地的變化,包括層出不窮的開發框架,諸如 React、Vue、Svelte,也包括日新月異的前端工程化工具,比如 Webpack、esbuild、Vite 等等。

          但歸根結底,他們都逃不開 HTML、CSS、JavaScript 三劍客的范疇。

          Web 技術生態成熟、穩定,然而卻存在一個致命的問題:使用 Web 技術去構建跨平臺應用程序并不是一件簡單的事情。

          這也是為什么許多平臺特定的框架(platform-specific frameworks)與跨平臺框架(cross-platform frameworks)依然受到歡迎的原因。

          比如其中最著名的跨平臺框架 Flutter,它部分基于瀏覽器引擎的技術,實現了「編寫一次,全平臺運行」的目標。而且這些框架,也基本不使用 HTML、CSS 這些 Web 技術。這是為什么呢?

          苦 HTML+CSS 久已

          因為 HTML 誕生的目的問題,以及 HTML 與 CSS 的開發體驗問題。

          HTML 即超文本標記語言,最初是三十年前為了制作可鏈接的文檔而發明的,而不是為了做應用程序。它更多是一種標記而不是一種語言。大多數人甚至都不將編寫 HTML 視為編程,因為它根本不是一種編程語言。

          直到出現 HTML5 (通常被稱為 H5)、CSS3 和 ES5 版本之后的 JavaScript,人們才逐漸開始用這些技術制作 Web 應用程序。在那之前,HTML 只是用于完成他最開始的目的。

          但做成 Web 應用的可行性,最大還是來自于 JavaScript 性能的提升。

          上面是 Lin Clark 介紹 JavaScript 性能歷史的一張圖。從2008年開始,JavaScript 性能就開始飛速提升。這對于應用程序的最終用戶來說有巨大的好處,因為做出來的應用程序終于不卡了,甚至可以對性能有所期待了。

          但是,對于開發者來說,仍然逃不開編寫 HTML+CSS。

          就算使用一些前沿的前端框架,如 React、Vue、Angular 等,我們仍然需要編寫類似 HTML 的代碼,并仔細調整 CSS 或者 CSS 預處理器(如 SCSS、Saas)的樣式表。

          這緩慢、枯燥、而且乏味。

          太多的人力、時間被浪費在實現圖形用戶界面的細節上,使用一些并不是一開始就為了 UI 而設計的技術。這導致開發者經常要來回調整樣式、處理瀏覽器兼容性問題、應用奇怪的 CSS 技巧、避開性能陷阱等等。

          另外,還需要在過度發展的 NPM 生態系統中,使用那些復雜的前端工程工具來進行應用程序的構建。這個過程效率也非常低下,開發體驗非常痛苦。更不要說 Web 應用在跨平臺需求中會遇到更多的陷阱,比如平臺兼容性、體積大小、性能問題,等等。

          此刻,我們質疑,堅持使用 HTML 和 CSS 的理由到底是什么?

          其他非 Web 框架

          然后我們再回過頭來看看其他的非 Web 框架。

          Electron 首先被我們排除。雖然微軟用它做出了 VSCode 這樣成熟的跨平臺應用程序,但也投入了巨大的成本,并且一般開發者可沒有這么雄厚的財力。

          但最關鍵的是,VSCode 其實是用 Web 技術做出來的,Electron 只是幫助它做成了跨平臺應用而已。

          看看我們還有什么其他選擇:

          • 有一些是自計算機黃金時代開始就存在的特定平臺的框架,例如 Windows 的 MFC,macOS 的 Cocoa,以及 UNIX/Linux 的 GTK。其他一些則是更現代的移動端框架,如專門為 iOS、Android 或其他移動操作系統專門服務的開發框架。
          • 而在跨平臺框架中,值得注意的是廣泛采用的 Qt 框架。但它主要用于桌面軟件開發。這里的跨平臺主要是指跨越不同的桌面操作系統,如 Windows/Linux/macOS,但這幾年 Qt 也逐漸在往移動端與 Web 端在努力,雖然沒有取得什么成就。
          • 第三種就是這幾年開始流行的全新跨端方案,如 Flutter,它是一個以移動端為主的跨平臺框架,但在 Web 端和桌面端也有所作為。

          隨著近年來 Web 應用的比例不斷增加,桌面端應用逐漸式微。但正是因為 Web 應用在跨端上的致命問題,這些非 Web 框架仍有一席之地,并且看上去也具有不可替代性。

          當然,其中的某些年代過于久遠的開發框架,開發人員的體驗甚至比編寫 HTML 更糟糕,因為他們可能被迫編寫類似于這樣的命令式和面向對象的代碼。

          var count=0
          let stack=new VStack
          let text=new Text("Count: \(count)")
          stack.add_child(text)
          let button=new Button("Increment")
          button.set_onclick(||
              count +=1
              text.set_text("Count: \(count)")
          )
          stack.add_child(button)

          不是編寫聲明式且響應式的代碼,就像程序員一直夢寐以求的這樣:

          struct AppState {
              count: i32
          }
          
          
          VStack {
              Text("count: \(state.count)")
              Button("Increment") {
                  state.count +=1
              }
          }

          這就是為什么 Flutter 看起來像是開發應用程序的靈丹妙藥:

          • Flutter 是聲明式且響應式的。
          • Flutter 真正實現了跨平臺,可以制作所有桌面、移動和 Web 應用程序。

          不過也還是有開發者不喜歡 Flutter,因為它引入了另一種新的、陌生的語言 Dart,以及額外的虛擬機負擔。

          Flutter 真正的問題在于與現有生態系統的兼容性,因為人們傾向于更喜歡重用已建立的資源和維護成熟的應用程序。編程語言也是出于同樣的原因。

          為了解決 Flutter 的一些問題,有些優秀開發者們嘗試開發了 Flutter 的 JavaScript 版本,雖然后來失敗了。因為 Flutter 本身正在迅速迭代,以至于兩者無法融洽。不過這部分的工作導致誕生了 Kraken 框架,它允許編碼人員編寫 HTML,并使用 Flutter 引擎進行跨平臺渲染。

          等等...發生了什么?在非 Web 框架中再次編寫 HTML?

          Design to Code

          不!再也不想寫 HTML 了!

          盡管如此,我們不得不承認,HTML+CSS 是表示 UI 的一個很好的組合,因為:

          • HTML 負責內容的結構,CSS 負責內容的樣式。
          • 結構和樣式是解耦的,這對工程來說是有好處的。

          但是在實踐中,UI 的工程有時是沒有意義且不必要的。假設我們已經有了設計師提供的高保真設計原型,編碼人員需要做的是:

          1. 使用代碼重新實現設計原型,這在 99% 的情況下是 HTML+CSS 的事情。
          2. 為剛剛重新實現的 UI 添加業務邏輯。

          第一部分總是讓人頭疼的源頭:涉及大量的細節、耗時、需要與設計師進行討論反復溝通,溝通成本很高,如果設計更新,代碼也需要更新,也許還需要另一場“昂貴”的討論。

          更不用說,這種工作通常被視為費時費力沒技術含量工作,也因此就有了大家聽到的前端程序員通常被其他非前端程序員所鄙視。

          一些聰明的開發者想出了使用編譯器技術或更具體地說是轉換器技術來實現設計到代碼的解決方案,將整個高保真設計轉換為機器生成的 HTML+CSS 代碼。這個就是所謂的 Design to Code。

          但它是為產品經理和設計師量身定制的,而不是為開發人員。這種內在問題包括但不限于:

          • 生成的代碼可讀性差,不符合項目中現有的編碼風格。
          • 生成代碼的不易集成。如果它依賴于另一個第三方庫怎么辦?如果生成的代碼更新了,整個大片的變化在版本控制系統中體現是否合理?
          • 像 Sketch 或 Figma 這樣的設計工具,總是可以設計出比 HTML+CSS 可以實現的更高級的視覺效果。他們甚至可以精確控制每一個像素。而很多時候,生成的代碼可能無法產生與設計原型完全相同的 UI,絕對需要一些補丁。但如果生成的代碼更新了,補丁就無法再應用了怎么辦?

          總之,從開發者的角度來看,Design to Code 不是一個好的技術解決方案。

          現在讓我們看看什么是 Design as Code。

          Design as Code

          在 VGG 所倡導的 Design as Code 開發流程中,用戶可以在某種程度上拋棄 HTML+CSS。

          因為設計稿完全替代了 HTML+CSS 的角色,設計就是代碼。請記住 VGG 的第一性原則:通過消除冗余的開發工作來彌合設計與開發兩方之間的巨大鴻溝。

          很明顯的優勢:圖形用戶界面的設計和開發只需要進行一次,因為兩者實際上是一體的。因此兩者的摩擦、討論會減少,這讓雙方都更高效。

          對于開發人員來說,他們能夠直接在設計文件上編寫業務邏輯,然后由 VGG 將其運行為一個交互式圖形應用程序。這可以節省大量重復的工作,不僅提高了開發人員的工作效率,也為整個團隊增加了工作效率。

          Design as Code 的想法很簡單,但它實現起來非常困難,比如會遇到來自編譯器技術、編程接口抽象和圖形渲染方面的工程挑戰。

          因此,為了實現 VGG 的 Design as Code 開發流程

          • VGG 定義了下一代矢量圖形規范 VGG Specs (https://docs.verygoodgraphics.com/specs/overview)
          • 實現了 VGG runtime 開源引擎 (https://github.com/verygoodgraphics/vgg_runtime)
          • 提供各種 VGG 容器,實現了對各種平臺和框架的嵌入式支持。

          VGG 天生就有著對開發生態很好的兼容性。相比于低代碼,VGG 是一套真正為開發者設計的工具。小結:

          • VGG 主打 Design as Code,直接使用設計稿代替 HTML+CSS 去實現用戶界面。
          • VGG 將設計稿變成了跨平臺的應用,為開發者節約了更多的時間與成本。

          基于以上兩點,VGG 以及它主打的 Design as Code 可以為現代交互式應用開發帶來巨大的好處。在最終用戶對用戶界面的實際使用效果沒有明顯感知差異的前提下,大大提升了應用開發者的開發體驗,甚至可以讓設計師、產品經理來承擔一部分的界面開發工作:無非是把現有的設計工具當作一個 UI Builder 來使用罷了。

          下面引用來自 VGG Github 首頁的一張圖,來更好地說明 Design as Code 的概念與 VGG 的有機組成:

          展望

          在這篇文章中,我們討論了 Web 技術、特定平臺的框架、跨平臺框架、Design to Code 解決方案以及基于 VGG 開源引擎的 Design as Code 開發流程。

          我們提出了 Design as Code 的概念,介紹了 VGG 作為一個全新的開發交互式圖形應用程序的框架。但 VGG 仍然年輕,因為還有許多技術挑戰需要克服,VGG 運行時引擎現已開源,歡迎大家一起參與 VGG 開源社區共建。

          關于 VGG 的更多細節將在后續的文章中討論。如果您感興趣,可以繼續閱讀官方博客和文檔
          https://blog.verygoodgraphics.com/

          現在大部分公司客戶端的開發基本上都選用Qt,很多以前用mfc寫的軟件也慢慢的用Qt重構,那么選Qt的原因是什么?Qt相比mfc的優勢又是什么呢?我認為有以下幾個原因:

          首先Qt跨平臺,除了正常軟件在多個平臺下能運行外,漂亮國對我國圍追堵截的今天,跨平臺這個特性對我們很重要,要在多個平臺下運行同一個軟件,避免對我們的卡脖子;

          其次QT做的GUI開發要比MFC要好,并且QT界面庫支持CSS,界面設計更方便更美觀,界面設計美工可以直接寫;

          面向對象的特性體現的比MFC明顯,在命名,繼承,類的組織等方面保持了優秀的一致性,代碼寫起來比較優雅;

          還有就是個人感覺Qt上手比mfc要快很多,要是不太麻煩的功能,用Qt實現起來比較方便,對新手更友好,我覺得這也是選擇Qt的一個很重要的原因,Qt現在功能越來越強大,做非GUI開發也挺好。再說了微軟已經停止對mfc的更新了,這也是軟件公司換到其他庫的一個原因吧。


          主站蜘蛛池模板: 3d动漫精品啪啪一区二区中文| 无码8090精品久久一区| 国产伦精品一区二区三区在线观看| 好看的电影网站亚洲一区| 午夜视频在线观看一区| 乱色精品无码一区二区国产盗| 亚洲国产成人久久一区久久| 中文字幕在线一区二区在线 | 99久久精品费精品国产一区二区 | 一区二区视频免费观看| 武侠古典一区二区三区中文| 麻豆视传媒一区二区三区| 国产嫖妓一区二区三区无码| 精品国产一区二区三区www| 日本一区二区三区精品视频| 国产一区精品视频| 日韩a无吗一区二区三区| 久久精品无码一区二区三区免费| 欧美激情一区二区三区成人| 手机福利视频一区二区| 午夜视频久久久久一区| 一区二区三区视频免费观看| 夜夜添无码一区二区三区| 国产精品福利一区二区久久| 国产日产久久高清欧美一区| 国产激情一区二区三区四区| 一区二区三区四区视频在线| 国产丝袜美女一区二区三区| 日韩成人一区ftp在线播放| 一区三区三区不卡| 国产不卡视频一区二区三区| 免费一区二区无码东京热| 亚洲日本久久一区二区va| 国产人妖视频一区二区| 亚洲AV香蕉一区区二区三区| 国产一区二区内射最近更新| 精品国产乱子伦一区二区三区| 成人在线观看一区| 国产一区二区三区在线影院 | 无码人妻一区二区三区在线视频 | 日本免费电影一区|