• <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>

            Loaden 個人專欄

            自學編程!
            posts - 0, comments - 0, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理
            re: Git Stash用法[未登錄] Loaden 2011-12-26 09:53
            stash是一個很有用的命令!
            不會用stash,說明不會用git!
            re: C++界面庫的抉擇[未登錄] Loaden 2010-08-26 13:00
            Qt并不適合個人開發小軟件的!
            Qt的最大缺點是LGPL無法靜態鏈接。
            這樣,你只能背著好幾十MB的DLL,這樣的程序發布出去,打包也要接近10MB。
            我想,這是無法讓人接受的!
            re: C++界面庫的抉擇[未登錄] Loaden 2010-08-26 12:57
            @陳梓瀚(vczh)
            Code::Blocks就是跨平臺的,使用wxWidgets庫開發。
            是你不會用罷了!
            什么將你的界面庫加進去呢?
            你的界面庫寫的很漂亮啊!
            re: wxWidget實現貼圖[未登錄] Loaden 2010-02-13 03:28
            很漂亮,要是放個完善后的wxSkin出來就更好了。
            或者放個Demo出來參考下。
            Qt真漂亮!強大,學習來了.
            x64下的thunk代碼還是有問題。
            普通thunk,非wndprocthunk。
            期待與你聯系。

            我的QQ:1090833
            下午還有課!雖然是星期天!!
            唉。
            這么好的文章,竟然只能晚上才能拜讀,遺憾啊!
            多謝cexer分享,期待下文...
            typeid.name()的問題,通過CSDN解決了。
            帖一下Demo。

            struct Create
            {
            bool handled;
            template<class T>
            static int GetEventId()
            {
            return T::IdCreate;
            };
            };

            struct Close
            {
            bool handled;
            template<typename T>
            static int GetEventId()
            {
            return T::IdClose;
            };
            };

            class A
            {
            public:
            enum
            {
            IdCreate,
            IdClose,
            TotalEvent
            };

            template <typename T>
            void Get()
            {
            printf("%d\n", T::GetEventId<A>());
            }
            };

            int main()
            {
            A a;
            a.Get<Create>();
            a.Get<Close>();
            return 0;
            }
            @ OwnWaterloo
            現在在理論上還可以有一種辦法將:
            m_testBtn.Get<EvtLButtonDown>(m_testBtn.IdLButtonDown).Bind(this, &MainFrm::OnLBtnClicked);
            Get<EvtCreate>(IdCreate).Bind(this, &MainFrm::OnCreate);
            簡化為:
            m_testBtn.Get<EvtLButtonDown>().Bind(this, &MainFrm::OnLBtnClicked);
            Get<EvtCreate>().Bind(this, &MainFrm::OnCreate);

            即不傳入enum的id,改由Get函數根據typeid(T).name去判斷id的值。
            但如何去實現呢?

            struct Create
            {
            bool handled;
            };

            class A
            {
            public:
            enum
            {
            IdCreate,
            TotalEvent
            };

            template <typename T>
            void Get()
            {
            // 這條語句輸出:struct Create
            printf("%s", typeid(T).name());
            // 可是,如何通過上面語句的輸出,來訪問: IdCreate呢?
            // 從“struct Create中獲取Create,在前面再加上Id,可以得到字符串IdCreate
            // 如何將這個字符串轉化為枚舉型變量的一個值,例如:IdCreate?
            //
            // 這兩行語句如何實現?
            // int i = IdCreate;
            // printf("%d", i);
            }
            };

            int main()
            {
            A a;
            a.Get<Create>();
            return 0;
            }

            一種比較容易想到的方案是:
            if (name=="A") id = ;
            else if (name=="B") id = ;
            但如果事件很多,這樣去比較,代碼寫起來很麻煩。
            而且編譯后的程序體積也是個問題。

            放到一個const字符串數組里,根據index判斷,由于const數組是占用內存的(VC占用,測試過,GCC不占用),所以這樣反而得不償失了。
            @ OwnWaterloo
            謝謝!
            我目前的方案,實現了每個可以發送消息的類,例如Button、Frame,至少需要8byte的代價,但:

            50個事件供Bind:至少12字節
            100個事件供Bind:至少20字節
            1000個事件供Bind:至少132字節
            10000個事件供Bind:至少1256字節
            而我之前每個事件用一個指針的方法,分別對應:
            200
            400
            4000
            40000
            代價下降了20倍。

            不過每個注冊的事件,還要多一個short + void*。
            由于用戶在一個程序中處理的事件不會很多,估計是總事件1/1000左右。
            所以也是很值得的。

            就算是一種低代價的實現吧。
            相應類的消息注冊類
            class ButtonEvt
            {
            public:
            enum EventId
            {
            IdLButtonDown,
            TotalEvent
            };

            IMPLEMENT_EVENT(EventId, TotalEvent);
            };

            class FrameEvt : public EvtSender
            {
            protected:
            FrameEvt(const String& keyEvt) : EvtSender(keyEvt) {}

            public:
            enum EventId
            {
            IdCreate,
            TotalEvent
            };

            IMPLEMENT_EVENT(EventId, TotalEvent);
            };

            這樣,只需要往enum里放不占內存的消息ID就行了。
            @ OwnWaterloo
            你用的是和atl一樣的方式?
            將hwnd"替換"為this? 而非"插入"一個this?
            是嗎?
            ====================
            是的。因為這樣才能兼容x64平臺:x64前8個參數通過寄存器傳遞。

            @ cexer
            SetProp 結合 GUID更理想,而GUID可以用API獲取。
            以后多交流!期待你的GUI框架下一篇...^_^

            ================
            |||||||||||||||||||||

            發現一個類中有6萬個指針時,如果指針初始化了,還是占用內存。
            沒辦法,為了降低成本,不能在類中放那么多指針了。
            所以,使用bitset來幫忙。

            先看消息注冊(比原來的難看多了,沒找到好方法,詳見:http://topic.csdn.net/u/20091119/15/07d7e755-c733-4195-8cc4-306560d6fbc4.html

            class MainFrm : public Frame
            {
            public:
            MainFrm() : Frame(_T("Test Demo!"), _T("MainFrame")), m_testBtn(_T("Test!"))
            {
            Add(&m_testBtn);
            m_testBtn.Get<EvtLButtonDown>(m_testBtn.IdLButtonDown).Bind(this, &MainFrm::OnLBtnClicked);
            Get<EvtCreate>(IdCreate).Bind(this, &MainFrm::OnCreate);
            }

            ~MainFrm()
            {
            Get<EvtCreate>(IdCreate).UnBind(this, &MainFrm::OnCreate);
            }

            qpEvt OnCreate(EvtCreate& evt)
            {
            qpDbgInt(evt.handled);
            }

            qpEvt OnLBtnClicked(EvtLButtonDown& evt)
            {
            qpDbgInt(evt.owner);
            }

            protected:
            Button m_testBtn;
            };

            用bitset + map<short, void*> + enum來降低成本:
            #define IMPLEMENT_EVENT(X, Y) \
            public: \
            template <typename T> \
            Event<T>& Get(X id) \
            { \
            if (m_evtMap.get() == NULL) \
            { \
            qpNewPtrEx(p, EventMap); \
            m_evtMap.reset(p); \
            } \
            if (m_evtFlag[id] == 0) \
            { \
            qpNewPtrEx(p, Event<T>); \
            if (p != NULL) \
            { \
            m_evtFlag[id] = 1; \
            m_evtMap->insert(std::make_pair(static_cast<short>(id), p)); \
            return *static_cast<Event<T>*>(p); \
            } \
            } \
            else \
            { \
            EventMap::iterator it = m_evtMap->find(static_cast<short>(id)); \
            if (it != m_evtMap->end()) return *static_cast<Event<T>*>(it->second); \
            } \
            qpASSERT(false); \
            qpNewPtrEx(p, Event<T>); \
            return *std::auto_ptr<Event<T>>(p); \
            } \
            protected: \
            typedef std::map<short, void*> EventMap; \
            std::auto_ptr<EventMap> m_evtMap; \
            std::bitset<Y> m_evtFlag;

            std::bitset的使用,可以判斷相應消息是否注冊,不用每一個消息都進入一次Event了,但由于使用map來查找消息,效率上還是下降了。
            沒辦法:只能用時間換空間!
            @ vczh
            我的網名叫老鄧(非羅登^_^),曾經在Live上向你請教過GUI框架設計。

            @ OwnWaterloo


            evt::Create evt = {wnd, this, reinterpret_cast<LPCREATESTRUCT>(lpa), false}; \
            ...
            this是怎么得到的?


            這是一個宏替換。宏所在的類的this就是這里的this。


            LRESULT CALLBACK Frame::WndProc(UINT msg, WPARAM wpa, LPARAM lpa)
            {
            ...
            估計也是非靜態的吧? 因為有m_wnd這些東西。
            那么,this是怎么得到的??

            非靜態。但只有三個參數,第一個參數通過匯編,寫到了m_wnd成員變量上了。沒辦法:兼容x64平臺,只能這樣thunk。

            另,昨天你教了我一下午,晚上我受到了啟發,想到了一個利用bitset的方法來降低成本。
            由于是動態注冊,所以運行成本增加了。

            f.Get<EvtCreate>(Frame::EvtCreate)->Bind(this, &A::test);

            而且,看起來不舒服。
            所以,今天準備結合你的union設計,把Get模板函數搞成屬性來訪問。
            如果Demo通過的話,我發gmail給你。
            @ OwnWaterloo
            糾正一下,是隨手 三 測 ^)^
            第三次改輸出代碼時崩潰的。
            @ OwnWaterloo

            肯定要調用的……
            不然怎么處理消息?
            -----

            消息處理在這個宏里。
            寫宏的原因是:不同消息處理類,可以通用。

            // WM_CREATE
            #define EVTCREATE(wnd, wpa, lpa) \
            case WM_CREATE: \
            { \
            evt::Create evt = {wnd, this, reinterpret_cast<LPCREATESTRUCT>(lpa), false}; \
            EvtCreate(evt); \
            } \
            return 0;
            struct Create
            {
            HWND wnd;
            Object* owner;
            LPCREATESTRUCT createStruct;
            bool handled;
            };
            因為編譯器知道這里肯定調用的是handle,不會是其他函數。
            但thunk,調用的地址是運行時的,所以編譯器無法優化。
            -----
            thunk不用調用,直接處理消息后,調用默認窗口過程。
            比如:
            LRESULT CALLBACK Frame::WndProc(UINT msg, WPARAM wpa, LPARAM lpa)
            {
            LRESULT res = 0;
            bool ret = ProcessMessage(msg, wpa, lpa, res);
            if (ret) return res;

            if (msg == WM_SIZE && m_layout != NULL)
            {
            m_layout->DoLayout(0.0f, 0.0f, static_cast<float>(X_LPARAM(lpa)),
            static_cast<float>(Y_LPARAM(lpa)), true);
            }

            switch (msg)
            {
            EVTCREATE(m_wnd, wpa, lpa);
            }

            return ::CallWindowProc(m_defWndProc, m_wnd, msg, wpa, lpa);
            }

            static函數...
            -----
            可能是個人喜好吧。
            我喜歡盡最大可能的 不 在C++中使用全局函數和靜態函數。
            我喜歡將什么東西都放在類里。
            哪怕是無法實例化的靜態類。

            我對你在前面給的“低代價”例子非常感興趣,下午準備好好學習你的例子。
            謝謝!!
            @ OwnWaterloo
            CWindow* w = (CWindow*)GetWindowLongPtr( ... );
            這個調用不僅僅是返回一個值而已。
            而且不同的窗口類,要返回不同的值。
            所以,這里編譯器如何優化呢?
            另外,static函數、全局函數也不利于C++封裝。
            而thunk,從其匯編代碼可以看到,代價只是多花1~3條CPU指令而已。
            顯然要高效。

            DEP的問題,我想過內存池來實現。
            不過由于技術不過硬,暫時還沒想過去實現它。

            先把GUI框架穩定下來再說。
            謝謝你的指點!如果有好的解決thunk的內存池(ATL就是這么干的,只是不開源),請介紹一個給我。
            @ OwnWaterloo
            因為要兼容x64平臺,所以統一使用__stdcall。
            原因是x64下只有__stdcall。

            DEP不是問題,很容易解決:
            void* operator new(size_t size)
            {
            return ::VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
            }

            void operator delete(void* p)
            {
            ::VirtualFree(p, 0, MEM_RELEASE);
            }

            而:
            Set/GetWindowLongPtr
            還有前幾天學到的…… Set/GetProp
            由于使用static函數,效率是一個大問題,而且有潛在的危險性。

            謝謝你分享:callback-currying
            其中qpEvt的定義:void __stdcall
            因為使用thunk,所以回調函數必須是__stdcall的調用約定。
            另,任何一個類如果要處理消息,需要這樣繼承:
            class Test : public EvtReceiver<Test>
            {
            public:
            Test();
            ~Test();

            void UnBind();

            private:
            qpEvt OnCreate(evt::Create& evt);
            };

            然后這樣注冊:
            Test::Test()
            {
            FrameEvt *sender = App::Module().GetEvtSender<FrameEvt>(_T("MainFrame"));
            if (sender != NULL)
            {
            sender->EvtCreate.Bind(this, &Test::OnCreate);
            }
            }

            Test::~Test()
            {
            }

            void Test::UnBind()
            {
            FrameEvt *sender = App::Module().GetEvtSender<FrameEvt>(_T("MainFrame"));
            if (sender != NULL)
            {
            sender->EvtCreate.UnBind(this, &Test::OnCreate);
            }
            }

            qpEvt Test::OnCreate(evt::Create& evt)
            {
            qpDbgInt(evt.handled);
            }

            但其中:
            FrameEvt *sender = App::Module().GetEvtSender<FrameEvt>(_T("MainFrame"));
            是極度齷齪的!可是我找不到更多的辦法了。
            @ OwnWaterloo
            能否QQ、gmail、Live聯系?有問題請教。
            我的QQ:1090833
            我的GMail、Live:loaden AT gmail or live dot com
            之前在gmail是向vczh請教時,受益匪淺。
            想結識牛人:不會啰嗦,只想在關鍵的疑惑上得到點撥。

            @ cexer
            非常期待你的GUI設計。
            我現在傾向于使用thunk封裝,但由于還碰到很多問題,沒辦法拿出來討論。
            非常期待能與你在QQ or GMail or Live上探討GUI框架設計。
            我目前實現的消息映射是這個樣子:
            [code]class MainFrm : public Frame
            {
            public:
            MainFrm() : Frame(_T("Test Demo!"), _T("MainFrame")), m_testBtn(_T("Test!"))
            {
            Add(&m_testBtn);
            m_testBtn.EvtLButtonDown.Bind(this, &MainFrm::OnLBtnClicked);
            this->EvtCreate.Bind(this, &MainFrm::OnCreate);
            }

            ~MainFrm()
            {
            this->EvtCreate.UnBind(this, &MainFrm::OnCreate);
            }

            qpEvt OnCreate(evt::Create& evt)
            {
            evt.handled = true;
            qpDbgInt(evt.handled);
            }

            qpEvt OnLBtnClicked(evt::LButtonDown& evt)
            {
            qpDbgInt(evt.owner);
            }

            protected:
            Button m_testBtn;
            };[/code]
            @ OwnWaterloo
            @ vczh
            (注:排名不分先后,按字母順序)

            你們兩個都是超級牛人!!我看你們的爭論時,更多的是自卑感!
            因為你們討論的很多東西我看不懂!!
            唉!!
            我把郁悶發在這里了,有空就過去給我簽個名吧。
            http://topic.csdn.net/u/20091117/19/54a04541-094f-4d7c-960e-c0ce34783821.html

            兩位不要傷了和氣!技術問題,有爭論總是好的!!
            我就在旁邊學習好了...
            強烈猛頂!
              寫到這,我作為輪子制造愛好者,在這里向那些喊著"不要重復制造輪子的"批評家們承認錯誤。在有那么多好的輪子的情況下,我不值得浪費地球資源,浪費時間精力來自己手工重復打造。但是不值得歸不值得,在值得和喜歡之間我還是選擇后者。并且人生在世,什么才是值得?我覺得不是拯救人類,為世界和平做貢獻,也不是努力奮斗,為地球人民謀福利,而是簡單地做自己喜歡的事。

            看來我和樓主是一樣類型。
            我也是從封裝類似ATL框架開發,目前正在模仿jlib2...
            還有很長的路要走!
            向樓主學習!
            我認為你的方法如果不是在基類中已經定義,那是無法實現的!
            能否帖出核心代碼?
            消息處理的很好!
            可是,new之后沒有delete?
            希望可以增加Code::Blocks支持,不知道項目難度如何,以及加入該項目有何要求?我原來從事過WTL開發。
            非常棒!!
            re: FLTK簡介[未登錄] Loaden 2009-05-26 20:24
            2.x對中文支持很好的。
            源碼使用UTF-8,GCC編譯器,中文顯示正常,輸入也正常。
            一個非常奇怪的問題:我編譯binutils成功,但make check總失敗。
            不知為何。
            博主你好!我只想編譯c/c++,使用make 及make install應該不行。
            于是我使用:
            make all-gcc all-target-libstdc++-v3 all-target-libssp all-target-libgcc && make install-gcc install-target-libstdc++-v3 install-target-libssp install-target-libgcc

            上面是通過configure之后的makefile文件自己判斷的。
            雖然我能編譯成功,但總出現crt2.o找不到的問題。

            另,我已經編譯MinGW好幾天了,有一些體會,但也有不少疑惑,想與博主QQ交流:1090833,能否加我QQ聊?
            mpfr也編譯成功了,正準備編譯gcc
            我編譯GMP4.3成功了,不過編譯mpfr出現錯誤。
            從VC8開發,VC的lib變了,不能再給MinGW用了。
            反過來也一樣。

            TDM版本還是不錯的。

            我正在嘗試編譯gcc4.4!
            mov qword ptr [rax], rcx
            這一行的機器碼不對,要改成:488908
            另,我在x64下用WinDBG調試發現:mov rcx, rax 的機器碼應該是:488bc8
            但如果用:4889c1 也可以。但我認為還是應該改成:488bc8

            不知道你看過ATL的atlstdcall.h沒有?如果能在他的基礎上實現thunk,可能更加完善。畢竟要修改第一個數據成員:這還是有局限性了。Thunk的功能打折扣了。

            但x64的難題是:前四個參數都在寄存器中。
            我目前的思路是:把前四個參數依次后移,將第四個參數入棧,可我只會點匯編的皮毛,能否指點一下如何實現?只要寫出匯編代碼即可,機器碼我可以通過WinDBG來調試得到。
            我在CSDN發了個求助帖,能否幫忙看看。
            http://topic.csdn.net/u/20090322/08/b6bf82ca-8ba2-452b-92f8-bb2adb05a1ef.html
            因為我匯編外行,所以只能嘗試修改。而我是在qemu虛擬x64機下測試,很慢。
            我覺得理論上完全行得通,但是否x64的匯編機器碼對應有誤?能否幫忙檢查一下。
            非常好的思路,可以實現跨x86和x64
            在x86下測試通過,但在x64下失敗:崩潰了。
            能否加我QQ:1090833,或我加你QQ,想請教一下崩潰的原因以及如何修正。
            有嚴重缺陷:如果用戶原來是管理員,后從管理員組中刪除,則上述代碼仍然認為是管理員。
            很好,非常感謝。可是無法下載了。如果可以,請發份一給:loaden AT gmail.com
            老色鬼久久亚洲AV综合| 精品久久久久久无码中文字幕一区| 国产99久久精品一区二区| 四虎国产精品免费久久久| 亚洲第一永久AV网站久久精品男人的天堂AV| 大蕉久久伊人中文字幕| 伊人久久大香线焦AV综合影院| 香港aa三级久久三级| 久久国产色AV免费看| 久久亚洲精品成人无码网站 | 曰曰摸天天摸人人看久久久| 国内精品久久久久久久亚洲 | 国内精品久久久久久久久电影网| 久久精品天天中文字幕人妻| 久久亚洲国产成人精品无码区| 日本三级久久网| 777午夜精品久久av蜜臀 | 久久91精品国产91久久小草| 麻豆av久久av盛宴av| 国产91久久综合| 国产精品国色综合久久| 久久午夜夜伦鲁鲁片免费无码影视| 亚洲狠狠久久综合一区77777 | 国产精品成人精品久久久| 久久偷看各类wc女厕嘘嘘| 久久综合亚洲色HEZYO社区| 久久影院久久香蕉国产线看观看| 亚洲综合精品香蕉久久网97| 99久久99这里只有免费费精品| 久久精品国产色蜜蜜麻豆| 欧美va久久久噜噜噜久久| 亚洲人成网站999久久久综合| 久久久久久久97| 久久伊人五月丁香狠狠色| 亚洲七七久久精品中文国产| 日韩AV毛片精品久久久| 中文字幕久久亚洲一区| 成人综合久久精品色婷婷| 中文字幕无码免费久久| 婷婷久久香蕉五月综合加勒比| 青青青青久久精品国产h|