青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-90  評論-947  文章-0  trackbacks-0

事情的緣起是,耐不住寂寞,準備開始造GUI的輪子。

GUI框架,要做的事情我想大概是這么幾步:

  1. 實現回調函數的成員化。
  2. 實現方便程度可接受的消息映射。
  3. 確定上述核心部件的使用方式。
  4. 制造大量的控件。

前三步要走的比較小心,第四步是體力勞動。

第一步,Windows下可參考的是MFC方式、WTL方式,以及利用Window相關屬性中的某些空位。前不久剛初步看過WTL的機制,雖然當時沒寫GUI框架的打算,不過也有點技術準備的意思了。現學現用吧。這里一個可以預見的問題是64位兼容,現在沒有測試環(huán)境,先不管。

接下來看第二步了,所要做的事情就是把 WndProc 下的 一堆 case 有效地組織起來,或者換個寫法。之前還真不知道 MFC/WTL 的 BEGIN_MSG_MAP。以為很高深的,想不到就是拼裝成一個大的 WndProc。先抄了,做成一個可運行的版本。但是,這方面會直接決定以后的大部分使用方式,單單抄一下意義不大。后來去 @OwnWaterloo 曾推薦過的 @cexer 的博客上逛了幾圈,第一圈看了一些描述性文字,第二圈大概看了下技術,第三圈是挖墳,那個傳說中的 cppblog 第一高樓啊。。其中有一個使用方式很新穎,嗯……是那個不需要手動寫映射代碼,直接實現消息處理函數的方式。不過我后來覺得還是不要這種樣子了,憑我個人的直覺,如果我寫下這樣的處理函數,我大概會因為不知道何時注冊了這個函數而找不到調用來源而感到郁悶。在Windows回調機制的影響下,我可能會很抱有偏見地認為,只有直接來自WndProc的調用,才算是來源明確的,不需要繼續(xù)追蹤的——當然,這是建立在我不熟悉這個框架的基礎上的。框架必然需要隱藏調用來源,以及其他一些細節(jié),但是在這一步,我覺得稍微有點早。

剛才說到的都是靜態(tài)綁定。現在我有點傾向于動態(tài)綁定。從使用方便程度上來看,動態(tài)綁定更具靈活性。從性能上,動態(tài)綁定下,消息到處理函數的查找過程可以更快,靜態(tài)綁定只能遍歷。當然,未必將“添加處理函數”這樣的接口提供給最終用戶,但是這個操作對于整個控件體系的形成應該蠻有幫助的吧。比如MFC下一個控件類使用Message Map做了一些事情,繼承類就無法直接繼承這個動作,于是可能需要做兩套處理函數調用機制,一套是給內部繼承用的,一套是給用戶的。如果在最開始的基類保存一個消息映射,每個消息對應一族處理函數,每個繼承類都可以添加處理函數,但不刪除父類已添加的函數,這樣就可以在一套Message Map機制下獲得父類的行為。以上,不知道考慮得對不對,歡迎討論。

其中,父類保存子類給出的可調用體并正確執(zhí)行是個問題。折騰了一些時間,都沒有成功。我比較糾結,想知道除了用function之類的玩意兒外還有沒有其他簡單可行的辦法。后來去@zblc的群上問,@vczh也說需要一套function機制。看來是逃不開這個問題了。嗯……想起來大約兩個月前一個同事從codeproject找來了一個GUI框架看,看到幾行整整齊齊的 AddMsgHandler(WM_CREATE, XXX(this, &MyWindow::OnCreate));,嘆不已。我當時打趣說,這很簡單的,無非是搞了個 function 而已,哥哥兩天就能搞定。于是他們叫我兩天搞定。我鼓搗了10分鐘,搞不定,只好丟一句,真的很簡單的,類似boost::function,你去看一下就知道了,哥哥要干活了。

既然現在還是繞不開這個問題,那還是搞一下了,搞好以后就權且當做給他們交作業(yè)吧。我會另寫一篇文章說說function的事情,這里先略過。現在開始假設這個設施已經造好了。那么,窗口類中大概可以這么定義相關類型:

typedef Function<bool (WPARAM, LPARAM)> MsgHandler;
typedef List<MsgHandler> MsgHandlerList;
typedef Map<UINT, MsgHandlerList> MsgMap;

然后再定義一個變量:

MsgMap  m_MsgMap;

它用于保存消息映射。最終的回調函數可以寫成:

LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    bool bHandled = false;

    MsgMap::Iterator itMsgMap = m_MsgMap.Find(uMsg);

    if (itMsgMap != m_MsgMap.End())
    {
        for (MsgHandlerList::Iterator it = itMsgMap->Value.Begin();
             !bHandled && it != itMsgMap->Value.End(); ++it)
        {
            bHandled = (*it)(wParam, lParam);
        }
    }

    return bHandled ? TRUE : DefWindowProc(m_hWnd, uMsg, wParam, lParam);
}

最后給個添加消息映射的接口:

void AppendMsgHandler(UINT uMsg, MsgHandler pMsgHandler)
{
    m_MsgMap[uMsg].PushBack(pMsgHandler);
}

到目前為止,我們的窗口類大致上可以寫成這樣:

#include <Windows.h>
#include <tchar.h>
#include "../GUIFramework/xlWindowBase.h"

class Window : public xl::WindowBase
{
public:
    Window()
    {
        AppendMsgHandler(WM_ERASEBKGND, MsgHandler(this, &Window::OnEraseBackground));
        AppendMsgHandler(WM_PAINT,      MsgHandler(this, &Window::OnPaint));
        AppendMsgHandler(WM_LBUTTONUP,  MsgHandler(this, &Window::OnLButtonUp));
        AppendMsgHandler(WM_RBUTTONUP,  MsgHandler(this, &Window::OnRButtonUp));
        AppendMsgHandler(WM_DESTROY,    MsgHandler(this, &Window::OnDestroy));
    }

protected:
    bool OnEraseBackground(WPARAM wParam, LPARAM lParam)
    {
        return false;
    }

    bool OnPaint(WPARAM wParam, LPARAM lParam)
    {
        PAINTSTRUCT ps = {};
        BeginPaint(m_hWnd, &ps);

        RECT rect = { 200, 200, 400, 400 };
        DrawText(ps.hdc, _T("Hello, world!"), -1, &rect, DT_CENTER | DT_VCENTER);

        EndPaint(m_hWnd, &ps);
        return false;
    }

    bool OnLButtonUp(WPARAM wParam, LPARAM lParam)
    {
        MessageBox(m_hWnd, _T("LButtonUp"), _T("Message"), MB_OK | MB_ICONINFORMATION);
        return false;
    }

    bool OnRButtonUp(WPARAM wParam, LPARAM lParam)
    {
        MessageBox(m_hWnd, _T("RButtonUp"), _T("Message"), MB_OK | MB_ICONINFORMATION);
        return false;
    }

    bool OnDestroy(WPARAM wParam, LPARAM lParam)
    {
        PostQuitMessage(0);
        return false;
    }
};

在最基礎的 WindowBase 里,搞成這樣大概差不是很多了。暫時先看第三步。到目前為止,我所聽說過的 GUI 框架都是真正的框架,似乎沒有“GUI 庫”。為什么一定要以繼承某個基類的方式來使用呢?如果像下面這樣使用呢?

class Window
{
private:
    xl::WindowBase m_WindowBase;

public:
    Window()
    {
        m_WindowBase.AppendMsgHandler(WM_ERASEBKGND, MsgHandler(this, &Window::OnEraseBackground));
        m_WindowBase.AppendMsgHandler(WM_PAINT,      MsgHandler(this, &Window::OnPaint));
        m_WindowBase.AppendMsgHandler(WM_LBUTTONUP,  MsgHandler(this, &Window::OnLButtonUp));
        m_WindowBase.AppendMsgHandler(WM_RBUTTONUP,  MsgHandler(this, &Window::OnRButtonUp));
        m_WindowBase.AppendMsgHandler(WM_DESTROY,    MsgHandler(this, &Window::OnDestroy));
    }
};

這個問題,不知道各位有沒有什么思考?

還有一個問題是,接下去要不要將 WPARAM 和 LPARAM 的含義徹底解析掉,搞成一系列 PaintParam、EraseBackgroundParam、LButtonUpParam、RButtonUpParam,DestroyParam,讓使用的時候與原始消息參數徹底隔離呢?

最后一步,雖說是體力活,但這跟最終的應用場合密切相關,需要提供怎么樣的功能是一件需要考量的事。

目前走在第二步,所以下面的兩個問題思考得不多。求經驗,求意見。

posted on 2011-01-16 20:05 溪流 閱讀(4235) 評論(11)  編輯 收藏 引用 所屬分類: C++Windows

評論:
# re: 也談談GUI框架 2011-01-17 01:06 | 飯中淹
這個GUI框架挺好的
我是保留WPARAM和LPARAM
不過一些常用的消息,做進了內部邏輯了。比如onpaint這種,在這個內部邏輯里,PARAM就被轉換成真實的變量了,比如HDC這樣的。

另外,我直接用VS的DIALOG編輯器,編輯成無窗口模式,然后用一個FORM套住這個無窗口模式的DIALOG,就間接實現了界面的所見即所得編輯。

用法,無所謂。可用就行。
  回復  更多評論
  
# re: 也談談GUI框架 2011-01-17 09:54 | right
覺得QT的sigslot用起來最舒服  回復  更多評論
  
# re: 也談談GUI框架 2011-01-17 11:59 | abeng
對GUI框架了解不多,不過如果能把QT跟DirectUI結合起來就完美了。  回復  更多評論
  
# re: 也談談GUI框架 2011-01-26 00:29 | 欲三更
按照我暫時的體會,我倒覺得GUI框架的難點不在你說的這幾個點上。我說說我的體會:

首先,基本庫的選型。基本的容器和算法可以使用stl,但是stl有個問題就是他是模板庫,可能會遇到版本和內存問題,而且stl的string類不太好用,至少在多種編碼方式共存的情況下不太好用,我的解決方法是自己寫一個string類,內部使用ucs-2,支持比較常用的編碼轉換,不常用的那些可以引入iconv。string用自己會帶來附加問題,就是一些基于字符串的功能要自己寫,比如常用的xml封裝等等,可以自己實現夠用的就行,也可以找支持多種編碼的庫來集成。

然后是GUI API的封裝,最常用的比如win21和Xwindows,這個其實也不好做,主要是要制定一套合理的接口和錯誤碼機制,這個要對幾種系統(tǒng)的功能覆蓋面和特點有全面的了解,以我現在的水平還不太行。而且這部分很繁雜。

再然后是類層次的設計,這個我們可以參考比較經典的實現,比如MFC或者QT。我個人比較喜歡的是borland的VCL,思想樸實但是絕對夠用。這里面比較復雜的部分是我覺得是:首先控件主要分兩種,一種是帶窗口id(win上師句柄)的,另一種是不帶id的,完全自己封裝的“偽控件”,這兩種結合在一起統(tǒng)一管理,不太好做。其次這一步如果不合理,那可擴展性就會變得不好。

接下來就是偽控件的實現,這個部分要實現的很多,要仿照原生控件實現z-order的管理,消息傳遞等等,要思考得很清楚才行。

再下來是渲染,我個人傾向于完全自己渲染,大部分人不同意,但是我覺的這樣更好實現界面的統(tǒng)一。如果自己渲染的話,首先得懂一點美工或者認識一個洞美工的給你把把關,不能太難看,其次分塊渲染這部分本來就不太好做,可以使用gdi+,但是跨平臺的話就得用一些開源庫比如agg。那你還得封裝一層,這個確實是工作量的問題。

下面的問題我和你的觀點倒是一樣的,就是回調函數的問題。這是個大問題,首先要實現回調函數成員化,這個不難,屬于小技巧吧,可能高手實現的話效率會好一點。但是回調函數和多線程結合起來,怎么做一個比較好的實現還是不容易,我是做了一個qt機制的簡化版,勉強能用吧,但是我覺得不太好。而且這里還有一個問題就是如果你的框架被用來寫模塊,主程序不是你的,怎么辦?比如我用你的框架寫了一個ActiveX,怎么搞。所以這個回調機制得是應單線程,同步,異步,以及沒有消息隊列的情況。我覺得高手來做的話這部分會很精彩,比如qt。

最后就是附帶性的問題了,比如怎么支持皮膚,怎么支持RAD開發(fā),是不是要支持外掛腳本。這些工作量絕對不小于核心功能的工作量。還有你說的大量空間,別的就不說了光一個彩色多字號的文本編輯器,就要用去不少時間了。

以上是我的想法,有點啰嗦,歡迎批評^_^  回復  更多評論
  
# re: 也談談GUI框架 2011-01-26 01:40 | 欲三更
順便說一句,你要是想如你所說把兩個param的解析徹底封裝起來,你這個MsgMap的模式可能要改。因為為了方便使用,對于不同消息可能要有一些特殊的處理步驟,而且你自己可能還要塞一些自己的消息進去,你可能得多封裝一層  回復  更多評論
  
# re: 也談談GUI框架 2011-02-15 14:48 | 小龍紅
@欲三更
ls分析得相當明了,做GUI框架工作就在與此吧。至于偽控件問題,我也建議盡量用這個實現,因為這樣就不需要windows的窗體資源,而且可以完全自己實現管理,統(tǒng)一資源管理。  回復  更多評論
  
# re: 也談談GUI框架 2011-02-16 00:38 | 溪流
@欲三更
謝謝你的分享~
控件工作量確實很多啊,標準的,自己的,才做了一個半~突然又有點不想解析 WPARAM LPARAM 了。。。  回復  更多評論
  
# re: 也談談GUI框架 2011-02-16 00:40 | 溪流
@abeng
@小龍紅
你們倆都有DirectUI傾向。。。就是因為不想要Windows來管理嗎?想了解下,Windows管理方式的那些方面值得我們拋棄它?  回復  更多評論
  
# re: 也談談GUI框架 2011-02-28 13:19 | zdhsoft
如果你了解一下VCL,估計會有新的收獲。  回復  更多評論
  
# re: 也談談GUI框架 2011-02-28 23:10 | 溪流
@zdhsoft
謝謝推薦,抽空一定看看  回復  更多評論
  
# re: 也談談GUI框架 2011-05-26 13:46 | 放屁阿狗
cpp的很多深入級的技術也琢磨了有一段時間,但最終還是要做項目,python成了我的首選,webservice,ice,gui native 全部使用python,前端的就用pyqt和flex來解決  回復  更多評論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久亚洲国产成人| 欧美日韩精品高清| 国产啪精品视频| 欧美亚洲免费电影| 性色av香蕉一区二区| 国产亚洲欧美在线| 老司机精品视频网站| 老司机aⅴ在线精品导航| 91久久精品一区二区三区| 亚洲丰满在线| 欧美性猛交99久久久久99按摩| 午夜精品剧场| 久久久水蜜桃av免费网站| 亚洲人午夜精品免费| 一本色道久久99精品综合| 国产拍揄自揄精品视频麻豆| 老鸭窝亚洲一区二区三区| 另类尿喷潮videofree | 久久国产精品久久久久久电车| 韩国av一区二区三区在线观看| 欧美77777| 国产精品分类| 另类av一区二区| 欧美日韩中文在线| 老司机67194精品线观看| 欧美精品v日韩精品v国产精品| 亚洲永久在线| 久久久久久亚洲综合影院红桃 | 国产九九视频一区二区三区| 久久先锋资源| 国产精品国产三级国产aⅴ浪潮| 久久伊人一区二区| 欧美日韩中文在线观看| 久久综合久久综合九色| 欧美日韩综合一区| 欧美chengren| 国产精品视频一区二区高潮| 欧美激情中文字幕在线| 国产日韩欧美不卡在线| 亚洲人体影院| 亚洲高清在线播放| 午夜久久影院| 亚洲无玛一区| 欧美成人性网| 噜噜噜91成人网| 国产日韩精品在线| 国产精品99久久久久久久久| 91久久久在线| 久久免费视频在线| 久久精品人人爽| 欧美色欧美亚洲高清在线视频| 欧美国产视频在线| 好看不卡的中文字幕| 亚洲欧美激情四射在线日| 亚洲色图制服丝袜| 欧美国产免费| 亚洲黄色影院| 亚洲国产视频一区| 久久免费国产精品1| 久久久不卡网国产精品一区| 国产精品激情电影| 国产精品99久久久久久人| 99视频在线观看一区三区| 免费在线亚洲欧美| 女生裸体视频一区二区三区 | 久久综合伊人77777蜜臀| 午夜精品久久久99热福利| 欧美日韩国产专区| 99国产精品自拍| 一区二区三区欧美激情| 欧美久久久久久久| 亚洲免费精品| 亚洲欧美久久久久一区二区三区| 欧美少妇一区二区| 亚洲一区三区电影在线观看| 性欧美1819sex性高清| 国产精品国产馆在线真实露脸| av72成人在线| 校园春色国产精品| 国产一在线精品一区在线观看| 欧美专区亚洲专区| 麻豆成人精品| 亚洲精选一区| 国产精品久久国产精品99gif| 亚洲一二区在线| 久久男人av资源网站| 在线观看欧美激情| 欧美精品日韩三级| 亚洲一区二区三区免费观看| 久久国产精品99久久久久久老狼| 国产日韩在线一区二区三区| 久久精品国产免费看久久精品| 欧美激情欧美激情在线五月| av72成人在线| 国产一区二区三区四区老人| 蜜桃久久精品乱码一区二区| 日韩视频一区二区在线观看| 欧美一区二视频| 亚洲人成毛片在线播放女女| 国产精品福利网| 久久精品夜色噜噜亚洲a∨| 亚洲国产网站| 欧美与黑人午夜性猛交久久久| 亚洲电影第1页| 欧美午夜电影完整版| 久久精品视频免费播放| 一本高清dvd不卡在线观看| 久久一区二区三区国产精品| 亚洲性夜色噜噜噜7777| 精品成人一区| 国产精品爽爽ⅴa在线观看| 久久久精品国产免费观看同学| 亚洲精品久久久蜜桃| 久久精品72免费观看| 最新热久久免费视频| 国产欧美在线视频| 欧美日韩一区二区在线视频| 欧美有码视频| 亚洲午夜黄色| 亚洲裸体视频| 欧美成人在线免费视频| 欧美一区二区久久久| 在线亚洲精品福利网址导航| 伊人狠狠色丁香综合尤物| 欧美午夜不卡| 欧美久久久久久久久久| 久久影音先锋| 久久深夜福利免费观看| 午夜国产精品影院在线观看| 亚洲三级免费| 亚洲激情视频在线| 欧美国产日韩一区二区| 老妇喷水一区二区三区| 午夜影院日韩| 性欧美xxxx视频在线观看| 在线综合亚洲欧美在线视频| 亚洲日本成人女熟在线观看| 黑人一区二区三区四区五区| 国产欧美 在线欧美| 国产精品久久久| 国产精品h在线观看| 国产精品国产a级| 国产精品久久久久久久久借妻 | 久久精品国产69国产精品亚洲 | 亚洲韩国青草视频| 亚洲高清中文字幕| 欧美激情中文字幕乱码免费| 欧美激情成人在线| 亚洲电影下载| 91久久久国产精品| 日韩午夜免费视频| 一区二区高清| 亚洲在线成人精品| 亚洲欧美一区二区激情| 性娇小13――14欧美| 午夜精品在线视频| 久久久久.com| 免费久久99精品国产自| 欧美精品18videos性欧美| 欧美日本韩国一区| 欧美婷婷六月丁香综合色| 国产精品久久久久高潮| 国产日韩欧美亚洲一区| 尤物视频一区二区| 日韩午夜在线观看视频| 亚洲视频在线观看| 欧美一区二区三区四区视频| 久久免费一区| 91久久久亚洲精品| 亚洲在线不卡| 久久综合一区二区三区| 欧美日韩精品在线观看| 国产精品一区久久久| 亚洲第一页中文字幕| 亚洲网址在线| 久久综合久久综合九色| 亚洲免费观看高清完整版在线观看| 亚洲小视频在线观看| 久久久久国产一区二区三区| 欧美久久九九| 国产一区三区三区| 一区二区三区国产在线| 性色一区二区| 亚洲人成亚洲人成在线观看图片| 亚洲网友自拍| 免费日本视频一区| 国产欧美日韩视频| 亚洲精品一区二| 久久午夜影视| 亚洲综合国产精品| 欧美大片在线看| 国产自产2019最新不卡| 在线亚洲一区| 欧美国产日韩亚洲一区| 欧美在线观看一区二区| 国产精品高潮久久| av成人免费在线观看| 免费成人在线视频网站| 亚洲欧美国产高清| 欧美日韩国产色站一区二区三区|