FunctionPtr

在持有的class(即要給他人使用的class)的class內先宣告
class CClassName4PtrFunc
{
public:
typedef void (CClassName4PtrFunc::*PtrFuncName) (arg...);

public:
void FuncName(arg...);

};


之後有要用的人則先在自己的head file內加入
class CClassName4PtrFunc;



需要使用時則在cpp內做以下動作即可
#include "CClassName4PtrFunc.h"

void CIWantUsePtrFunc::UsePtrFunc(arg...)
{
CClassName4PtrFunc::PtrFuncName pPtrFunc;

(*pPtrFunc)(agr...);
}


上面內容目前還沒測過,僅用於memo用。
有誤還煩請指教。

[MFC]CListCtrl自動選擇一行

m_List.SetItemState(nIndex, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
m_List.EnsureVisible(nIndex, FALSE);

不過使用上面方式後的選擇顯示是灰色的標記,並不是用滑鼠點選時的藍色。

如果需要選擇成藍色則如下:
m_List.SetItemState(nIndex, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
m_List.EnsureVisible(nIndex, FALSE);
m_List.SetFocus();

但是方法僅能用在按下按鈕的同時。

如有需要在另外的Thread中來做SetFocus(),則需使用SendMessage的方式來達成。

未指定大小的vector取址問題

目前使用vector來當做資料儲存用的array(這邊的資料都是用copy的方式存入vector),剛好又需要在thread內要去更新vector內的資料。
所以是利用取址的方式來將資料寫回原本使用的vector內。

此時發生只要有新資料進來的時候,原本取到的位置的值會被變更。

這邊是懷疑因為vector自動重新分配大小時,會將原本的就資料搬到新的記憶體位置。
所以原本參照的位置就變成沒有使用或是被別的變數使用了,所以導致只要有新資料進來,值就錯誤的問題。

後來重新於一開始就設定vector的capacity,之後下去運作後,先前的問題就都不見了,所以有以上之推論。

不過在map上並沒有發生類似的狀況,所以這邊還需要在詳查一下吧

[WinAPI]FindWindow在Vista的奇異事件

話說最近嘗試透過PostMessage(HWND hwnd, LPARAM lpParam)要將一比資料從一個視窗程式傳到另一個視窗程式,這時候由於第一個程式的hWnd第二隻並不知道。所以這邊在第二個程式啟動的時候,就利用FindWindow來尋找第一個程式的hWnd。

在XP x32/x64以及Vista x64的平台上測試,都可以正正確確的找到第一個程式的hWnd。但是在"某台特定"的Vista x32上卻發生第二個程式永遠抓到一組固定的hWnd,即使是第一個程式有重開過。

這個現象就非常的不合理,因為每次視窗重新產生的時候,都會有不同的hWnd,所以這邊的FindWindow抓到了誰,那就不得而知了。所以這邊在做PostMessgae的時候,想當然,資料就永遠傳不到第一個程式了。

後來在網路上搜尋了一下,發現還有EnumWindow(WNDENUMPROC EnumProc, LPARAM lParam)可以用來取得所有視窗的hWnd。這個API還須透過一個Callback function來使用,就是EnumWindowProc(HWND hWnd, LPARAM lParam)。第二個參數看個人需求可選擇自行傳遞,這邊是因為要取得第一個程式的hWnd,所以這邊是傳入第一個程式的PID。

由於這邊是使用PID來比對,所以還需要透過GetWindowThreadProcessId(HWND hWnd,LPDWORD lpdwProcessId)來取得目前所列舉的視窗的PID。

之後就可以利用取得之hWnd來進行PostMessage了。

Callback的範例如下
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
DWORD iPID = 0;

if ( GetWindowThreadProcessId(hwnd, &iPID) != NULL )
{
if ( iPID == (DWORD)lParam )
{
m_1sthWnd = hwnd;
return FALSE; //Find the PID and stop the callback function
}
}
return TRUE; //Continue the callback function
}


EnumWindow使用範例如下
::EnumWindows(&EnumWindowsProc, (LPARAM)m_1stPID);

2009/Sep/30-Add
不過這種方法在遇到會換hWnd的Dialog下就會出問題(目前我遇到的是切換combo會造成hWnd的變更),所以最保險的還是用FindWindow會比較好。

不過還是要找比較安全的作法才行。

[WinAPI]GetFileAttributes在Vista 64的%AppData%下無法正確判定是否為資料夾

一般在判定取得的路徑為檔案路徑或是資料夾路徑時,可透過GetFileAttributes來得知路徑的屬性。

這個方法在XP的版本下的時候,都可以正常取得到FILE_ATTRIBUTE_DIRECTORY,所以也可以正常的判定是否為資料夾。

然而在Vista上任意的路徑(如桌面、All User等)內的資料夾或是檔案路徑也都可以正常判定。

但是當路徑內轉指向%AppData%(c:\Users\CurUsrName\AppData\Roaming)的時候,如也是透過GetFileAttributes來取得路徑屬性的話,資料夾部分則會得到8208、檔案則會得到8224兩組值。

這兩組值並沒有在MSDN內被提供(http://msdn.microsoft.com/en-us/library/aa364944(VS.85).aspx)

所以後來經過Jacob的提醒,去檢查了這兩組值的binary值。
發現
8208 = 10 0000 0001 0000
8248 = 10 0000 0010 0000

這與
FILE_ATTRIBUTE_DIRECTORY = 00 0000 0001 0000
FILE_ATTRIBUTE_ARCHIVE = 00 0000 0010 0000

差了一個最高位的屬性。

所以這邊就根據Jacob的建議,在屬性判斷時,多做了BitMask來過濾掉其他不相干的屬性。

所以目前處理方式如下

```cpp
switch ( GetFileAttributes(szPath) & FILE_ATTRIBUTE_DIRECTORY )
{
case FILE_ATTRIBUTE_DIRECTORY:
  return IS_DIR;
case FILE_ATTRIBUTE_ARCHIVE:
  return IS_FILE;
case INVALID_FILE_ATTRIBUTES:
  return IS_INVALID;
default:
  return IS_UNKNOWN;
}
```

至於最高位的那個bit是啥用途,那就等候M$大帝國公布啦XD

printf內要顯示%符號

就只要在%前面再多加一個%就可以了。

這邊可不是用escape(\)喔。

[Linux]malloc_usable_size使用注意事項

在windows下有個可以取得malloc的buffer size的函式-_msize()。

然而在linux底下是沒有相同的函式,所以後來又去網路上找到malloc_usable_size()這個函式。

雖然malloc_usable_size()可以取得到buffer size,不過呢,因為他是dependence on aligment。

所以取得的大小會等於或大於原本buffer size,如果要用來作比對或者是buffer大小計算的話,這邊就很容易出錯了。

至於替代方案目前還沒找到,所以有找到後再補上吧。

以下是參考連結:
http://www.slac.stanford.edu/comp/unix/package/rtems/doc/html/libc/libc.info.malloc.html


以下是部分文字節錄:
   The `malloc_usable_size' function takes a pointer to a block
allocated by `malloc'. It returns the amount of space that is
available in the block. This may or may not be more than the size
requested from `malloc', due to alignment or minimum size constraints.

[VS神奇事件]pThread->InitInstance()發生crash事件

自從前述的libary link被修改事件被處理完成之後,再度又發生一個非常神奇的事件。

就是原本一個console application在run-time的時候crash了,crash的地方是在pThread->InitInstance()的地方。

在debug模式下發現這邊的pThread其實是一個NULL,所以會當掉也是很正常的。

然而這個pThread是放在AfxWinMain()底下,而AfxWinMain是在winmain.cpp裡面。

問題來了,一個console程式為何會需要用到winmain這個函式呢?

正在苦無解法的情況下,google到了這篇文章(http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/0ba47667-5067-4dc9-b667-87d40d7e2566)。

所以就照他的方法到了link底下的subsystem去檢查設定(Project->Properties->link->subsystem)。

結果,Bingo!!
M$的產品總是充滿驚喜阿,subsystem的設定竟然是winodws阿。

一整個無言,為何好端端的console程式會變成windows程式呢?

更何況3個月前他還是console阿,所以最後就把subsystem的設定調回console後,程式又可以正常運行了。

所以,M$讓我們的生活總是充滿驚喜阿!!!XD

[VS神奇事件]Visual Studio無法開啟Find and Replace window-1

這個事件後來還是有發生,不過這次有經驗了,所以也就沒有在做solution的reset的動作XD

不過這次倒是有發現原因了。

主要Find and Replace window會跳的原因是因為只要這個視窗擋到被修改或是被搜尋的文字的時候,他會自動跳到不會遮住的地方,至於怎麼跳,那這邊要問M$,目前看不出他的patten。

而會跳到工作列下面是因為當初在做取代的時候,是用select的方式,所以等於整個被修改的文字都會被Find and Replace window給遮住了,而Find and Replace window為了不遮住那些被修改的文字,所以就跳到不會遮到的地方,也就是Text Editor外面。

不過後來在做測試的時候,Find and Replace window就沒有跳到工作列下面去了,所以這問題是要不小心使用的時候才會發生嗎?XD

PS.以上發生原因是經過數次實驗後所做的假設,不過解決方法倒是可行。至於實際原因就要問M$了XD

[VS神奇事件]LNK2019

最近把原本在windows上運作的程式porting到Linux上,在porting的過程中也沒有去改VS的專案設定。

在porting完成後想說在Windows上build看看原本的程式。結果卻在某個中間dll專案發生了LNK2019的問題,在整個檢查過程中發現所有原本要做dllexport的class全部都變成dllimport了,這時還以為是因為pre-processor key的部份沒有做設定,還特地把專案一個一個測試。

結果,問題並不是出在那邊,雖然VS的顯示上本來就有問題,但是那還不致於影響compiler的編譯。最後因為上網去找有關LNK2019的相關文獻發現,這問題在dll載入的動作中,是代表靜態連結有問題。

所以後來就去檢查專案的lib link,後來發現,果真,原本設定的那些lib link全部都不見了。
後來把原本該有的lib link都加上去後,complier就可以正常編譯了。

話說,這是VS的bug嗎?竟然把之前設定的資料都弄不見了?XD

就是因為相同的舊專案可以build,所以就沒懷疑到這邊。結果花了3天的時間在抓這問題,一整個殘念阿 -.-

Build docker image from multiple build contexts

Build docker image from multiple build contexts ...