發表文章

目前顯示的是 2013的文章

【已解決】CResourceException 異常處理

圖片
最近開發一個自訂控制項,當視窗經過多次放大、縮小後就會產生 First-chance exception at 0x000007fefcfe940d in XXX_x64.exe: Microsoft C++ exception: CResourceException * __ptr64 at memory location 0x0027b360.. First-chance exception at 0x000007fefcfe940d in XXX_x64.exe: Microsoft C++ exception: CInvalidArgException * __ptr64 at memory location 0x00276b90.. Warning: Uncaught exception in WindowProc (returning 0). 經過搜尋的結果,應該是使用資源後未釋放,造成資源耗盡。問題是沒有捕捉到產生異常的地方,要修改也無從下手。於是先用 try catch 在有可能的地方試試看

[已解決] Ubuntu 12.04 LTS 無法連接網路

日前在公司的 Z87 主機板上安裝 Ubuntu 12.04 LTS 後,才發現網路無法使用,經過一番 Google 後才知道是晶片太新,Ubuntu kernel 不支援,只好手動安裝 Driver 了。所幸不太複雜,為了怕以後還要再來一次,所以就先記錄一下。 首先到 Network Adapter Driver for PCI-E Gigabit Network Connections under Linux* 下載 Driver 接下來三個步驟就搞定了 tar zxf e1000e-<x.x.x>.tar.gz cd e1000e-<x.x.x>/src/ sudo make install sudo modprobe e1000e insmod e1000e 參考:intel Network Connectivity Linux* e1000e Base Driver overview and installation 2013/9/16 今天的 Ubuntu 網路忽然又不能用了,於是又讀了一遍 e1000e 的 Readme,發現有可能是舊版的 e1000e Driver 所造成的,於是依照下列的步驟:先移除舊的,然後再安裝一次就 OK 了! sudo rmmod e1000e sudo modprobe e1000e

利用 GRUB2 掛載 ISO 檔安裝 OS

以前要安裝新的 OS 總是要利用光碟片來開機才能安裝,但最近碰到光碟機會挑片,無法讀取單面雙層的 DVD,每次要安裝還得跟別人借光碟機,實在有夠麻煩! 後來偶然間看到 Grub2/ISOBoot 才發現:原來 GRUB2 不只可以掛載 Partition,也可以掛載 ISO 檔模擬成光碟機 (類似 Windows 下的虛擬光碟機),這樣就可以安裝了,而且速度還比實體光碟機快多了,反正現在硬碟空間那麼大,不在乎存放 ISO 檔的那一點點空間!

使用 googletest & googlemock 做單元測試

svn checkout http://googlemock.googlecode.com/svn/trunk/ (已包含 googletest) 將來可以直接用 svn update 為了方便將這兩個 Framework 加入測試專案,將輸出目錄由 SolutionName 改為 SolutionDir ,避免附加到不同的 Solution 時造成名稱不一致 (後來發現一般  Project 都是用 SolutionDir,唯獨這兩個 Project 使用 SolutionName,怪哉!) 開啟 googlemock\gtest\msvc\gtest-md.sln,點選 gtest-md 的 Properties,選擇 All Configurations,將 General | Output Directory 由 $(SolutionName)/$(ConfigurationName) 改為  $(SolutionDir)/$(ConfigurationName) 開啟 googlemock\msvc\2005\gmock.sln 點選 gmock 的 Properties,選擇 All Configurations,將 General | Output Directory 由 $(SolutionName)/$(ConfigurationName) 改為  $(SolutionDir)/$(ConfigurationName) 選擇 Debug Configuration,將 C/C++ | Code Generation | Runtime Library 由 Multi-threaded Debug (/MTd) 改為 Multi-threaded Debug DLL (/MDd) 選擇 Release Configuration,將 C/C++ | Code Generation | Runtime Library 由 Multi-threaded (/MT) 改為 Multi-threaded DLL (/MD) 以上動作設定一次即可 PS : 如果 Project Runtime Library  使用 Multi-threaded (Debug) DLL,則 MFC 必須使用 Shared DLL;反之若使

scanf 兩三事

圖片
記得以前寫程式的時候,scanf 是很常用到的輸入功能。但寫 Windows 程式後就很少碰到它了,直到之前發生了一些靈異現像,才重新勾起對它的回憶。首先看看以下的程式碼吧 int _tmain(int argc, _TCHAR* argv[]) { short int i=0, j=0; _tprintf(_T("Please input number : ")); _tscanf_s(_T(" %d "),&i); _tprintf(_T("i = %d, j = %d\n"), i, j); return 0; }

[已解決] Static Library Project 的 MFC 不支援 template

最近為了用 Unit Test 而將一些程式碼放在 Static Library Project 中,但在使用 CArray template 時卻出現 Compiler error C2976: 'CArray' : too few template arguments 經比對一般的 MFC Project 才發現 stdafx.h 未加入 #include <afxtempl.h> 加入後就一切正常了 Test project 也要加入,而且設定使用 Shared DLL MFC 才能正常測試

operator LPCTSTR() 實作

在 C# 裡有一個 ToString() 的方法可以把物件的內容轉為字串,但在 C++ 中卻找不到對應的方法。後來看到 CString 覆寫 operator LPCTSTR() ,才驚覺原來還有這種作法啊! class MyClass { private: TCHAR m_lpszName[MAX_PATH]; public: MyClass(LPCTSTR lpszName); ~MyClass(void); operator LPCTSTR() const; };

C Bit Field 使用注意事項

圖片
C Bit Field 在存取暫存器的欄位是非常好用的,例如

鍵盤、滑鼠失去電力囉!

先前為了開發新的程式,整個硬體平台更換後,原本的硬碟進到 Windows 的畫面卻無法登入,請高手來查看後才發現鍵盤、滑鼠接的 USB Port 沒有電 (開機時還有),我猜想可能是 Windows Driver 未載入 (或是找不到),所以沒有開啟電源吧,當初也忘了記錄他是怎麼解決的。 結果前幾天更新主機板 BIOS 時,又發生一樣的情況,不想麻煩別人來用,直接詢問的結果竟然是重新插拔鍵盤、滑鼠就好了,真是太神奇了!

【已解決】刪除指向介面指標 (Interface pointer) 的物件不會執行解構函式 (Destructor)

一般物件在生命週期結束時,會呼叫解構函式,以便執行釋放資源的動作。但對於實作介面的物件,如果是以介面指標的方式來呼叫,竟然不會呼叫解構函式,Oh My God。讓我們一步一步來看看吧! #include "stdafx.h" #include <iostream> using namespace std; struct IAnimal { virtual void Eat() = 0; }; class Dog : public IAnimal { public: Dog() { cout << "Dog construct." << endl; } ~Dog() { cout << "Dog destruct." << endl; } void Eat() { cout << "Dog eat ..." << endl; } }; int _tmain(int argc, _TCHAR* argv[]) { Dog* pDog = new Dog(); pDog->Eat(); delete pDog; return 0; }

【已解決】C++ Event 的實作方式

Event 在 Windows 的程式設計中,已經習以為常,尤其是 Windows 的 Event。但要在 C++ 中實作,還真不曉得要如何下手,原本在 C# 中如此基本的東西,轉到 C++ 竟是如此困難。 還好 Microsoft 還是留了一手 Event Handling ,但看了半天還不是很懂,於是從 Sample code 中實驗終於大致瞭解了,所以記錄以備後用 (雖然 Microsoft 說這個功能要取消了,不過取消前還是將就著用吧!)

【已解決】循環引用的疑問

最近在移植程式的過程中,碰到一個循環引用的問題,困擾了我不少時間,所以有寫下來的必要,以免下次再犯。直接來看例子吧! 這是最上層的介面 IElement,其中的 Method 可以處理實作 IVisitor 介面的物件 #pragma once #include "IVisitor.h" // <== Cause cross reference struct IElement { virtual VOID Accept(IVisitor* pVisitor) = 0; virtual VOID Traverse(IVisitor* pVisitor) = 0; }; typedef IElement* PIElement; 接下來是 IComputer 介面,繼承 IElement 介面

在 C++ 使用 namespace

寫程式常常會碰到名稱 (類別、函式、變數 ... 等等) 衝突的問題 (因為英文懂得太少了),這個時候命名空間就可以發揮功用了,只要在自己的命名空間內,即使名稱跟別人一樣也不會衝突了。 同時在 Visual Studio 的 Class View 中,也會依據命名空間來分類,方便 Source Code 的管理。唯一的缺憾就是不能像  Net 一樣使用 "." 當作命名空間的名稱,所以只好用 "_" 來取代了!

好玩的 manifest

圖片
先前在  Tooltip Controls  曾經提到 Manifest,當時還不甚瞭解,而今天又碰到類似的問題,所以決定作個實驗來澄清一下! 首先找個專案來設定,把 Embed Manifest 設為 No ,也就是把 Manifest file 放在外面,不要內嵌到程式中

The Desktop Item Position Saver (DIPS) Utility 程式解析

圖片
前言: DIPS Utility ( Windows via C/C++, Fifth Edition Page 633) 是 Jeffrey Richter 示範 DLL Injection 的一個範例,內容讀起來對我來說有點複雜,所以做一下心得報告以加深印象。

【已解決】Global Hook 抓不到其它的程式

圖片
Hook 對我來說是一個全新的東西,它的概念有點像以前在寫 DOS TSR (常駐程式) 的作法,必須攔截原本的中斷,然後改成呼叫自己的中斷服務常式,但自己的服務常式中又必須呼叫原本的中斷,以達到插入自己程式碼到系統中目的。 我實作的是 WH_CBT 的 Hook,當一個視窗有動作時 (包含 activating, creating, destroying, minimizing, maximizing, moving, or sizing) 都會呼叫這個 Hook,根據 MSDN 的說明,把 CBTProc 放在 DLL 中可以達到 Global Hook 的目的。 但奇怪的是,在偵錯的過程中,我把中斷點設在 CBTProc,只有點到我自己的程式時才有反應,點到其它的程式完全沒反應,不是 Global Hook 嗎?為甚麼點別的程式會攔截不到呢?

SVN 心得

參考: Subversion(SVN)概念與工具介紹 Checkout (取出):與 Server 保持連結,可 Commit (送交) 與 Server 同步 Export (匯出):僅下載副本,未保持連結 Delete:刪除檔案, 若在 Checkout 的資料夾中直接刪除檔案,並不會刪除 SVN  上的檔案 ;必須用 SVN Delete  才可以 Branch/tag:產生分支,差別在 Branch  可以繼續修改,而 tag 不行 (Read only) Merge:選擇 Merge a range of revisions ,例如在 trunk ( Target ) 的 Working Copy 選擇合併 branch ( Source ) 的某一個版本,則合併的結果是在 Working Copy,branch 跟 trunk 不會有任何影響,除非 Commit 才會更新到 trunk。而在 Working Copy 可以用 Diff 比較差異的部份,決定採用那一個版本或共用。而 Merge 的方向可以是將 trunk 的變更同步更新到 branch;或者將完成的 branch 合併到 trunk (參考: 講解 Subversion 分支與合併:以 TortoiseSVN 為例 ) Switch:將 Working Copy 切換到不同的 branch 或 tag,但 Working Copy 如果未 Commit 有可能會出現衝突的情況 Revert : 還原到修改前的狀態 若要還原到先前已經 Commit 過的版本,可以先開啟 Log Messages,然後在要還原的版本上按滑鼠右鍵,選擇 "Revert to this revision",最後再重新 Commit 一次即可 建議在 Settings | General | Global ingore pattern 附加以下設定 (參考: What should be contained in a global source code control ignore pattern for Visual Studio 2010? ) *.ilk *.aps *.suo *.ncb *.user *.opt *.plg Debug Release debu

從 Visual Studio 2008 編譯 DevCon

圖片
Device Console (DevCon) Tool  是一個命令列下的工具程式,可以用來管理電腦上的 Driver,而我就需要它來重新啟動 Display driver。(節錄 實作步驟 ) DevCon 是 WDK  內的一項工具,為了要相容 Windows XP,所以安裝 WDK 7.1.0

數位簽章自動化

圖片
在公司寫程式果然不一樣,出去都要加數位簽章以示負責。原本的做法是等程式編譯完成後,再以手動的方式加入,不過每次都要這樣加實在太麻煩了,所以就把它加入 Project Post-Build Event  中,這樣就可以達到自動化的目的了 首先把 Project Property Pages 叫出來,只有 Release Build 需要加數位簽章,所以 Configuration 選擇 Release 即可。打開 Build Events 的  Post-Build Event,把要執行的動作寫在 Command Line 中,順便在 Description 中輸入一些說明,以便在編譯的輸出中可以識別。

Tooltip Controls

圖片
最近工作上需要用到 Windows API 來實作 Tooltip 的功能,所以就開始在網路上找 Sample code 來參考,可是奇怪的是:怎麼試都顯示不出來 // Description: // Creates a tooltip for an item in a dialog box. // Parameters: // idTool - identifier of an dialog box item. // nDlg - window handle of the dialog box. // pszText - string to use as the tooltip text. // Returns: // The handle to the tooltip. // HWND CreateToolTip(int toolID, HWND hDlg, PTSTR pszText) { if (!toolID || !hDlg || !pszText) { return FALSE; } // Get the window of the tool. HWND hwndTool = GetDlgItem(hDlg, toolID); // Create the tooltip. g_hInst is the global instance handle. HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL, WS_POPUP |TTS_ALWAYSTIP | TTS_BALLOON, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hDlg, NULL, g_hInst, NULL); if (!hwndT