最近有網友來信詢問於在LabVIEW中如何使用”User32.dll”中API EnumWindows,由於它是使用callback的方式傳回資料因此需封裝成dll的形式給LabVIEW使用,本篇將介紹此過程的程式撰寫方式。
在LabVIEW中若想要使用dll來註冊Event,dll必須加入extcode.h這個檔頭和使用Library檔labview.lib或labviewv.lib。
在LabVIEW中若想要使用dll來註冊Event,dll必須加入extcode.h這個檔頭和使用Library檔labview.lib或labviewv.lib。
對於到底是使用labview.lib或labviewv.lib,根據這篇文章(labview.lib or labviewv.lib?[http://forums.ni.com/t5/LabVIEW/labview-lib-or-labviewv-lib/td-p/2916894]),我的理解是為了對應不同版本的LabVIEW RunTime,應該要使用labviewv.lib。
首先由微軟的MSDN查看EnumWindows的使用說明:
BOOL WINAPI EnumWindows(
_In_ WNDENUMPROC lpEnumFunc,
_In_ LPARAM lParam
);
Parameters
lpEnumFunc [in]
Type: WNDENUMPROC
lParam [in]
Type: LPARAM
An
application-defined value to be passed to the callback function.
Return value
Type:
Type: BOOL
If the function succeeds, the return value is nonzero.
由此可看出EnumWindows需要輸入的參數,lpEnumFunc 就是callback函數的原型,要傳入實作函數程式碼的位址,lParam 則是輸入的參數,要傳入未定的資料型態位址。
BOOL CALLBACK EnumWindowsProc(
_In_ HWND hwnd,
_In_ LPARAM lParam
);
Parameters
hwnd [in]
A handle to a top-level window.
lParam [in]
Return value
To continue
enumeration, the callback function must return TRUE; to stop enumeration, it must return
FALSE.
由此可知EnumWindowsProc這個callback函數的原型宣告方式,當callback發生時系統會提供hwnd就是我們想要列舉的程式handle值,而lParam在這邊並沒有用到。
有了這些資訊就可以開始編寫提供給LabVIEW的dll了,首先先定義回傳給LabVIEW的資料型態,由於希望取得的是目標程式的類別字串和視窗名稱自串,因此宣告一個結構包和兩個字串:
typedef struct tagStrRec {
LStrHandle Str1;
LStrHandle Str2;
} StrRec, *StrRecPtr;
這樣的話在LabVIEW的部分就可以解成cluster包含兩個String的結構。
接著宣告全局變數用於儲存LabVIEW UserEvent的位址和常數。
// 紀錄LabVIEW UserEvent的位址
LVUserEventRef EnumWindowsEvent;
// 預設最長字串長度為256 Bytes
#define STRING_LENGHT 256
然後再宣告dll輸出的函數:
//用於註冊LabVIEW事件
MgErr __declspec(dllexport) __cdecl
RegisterEnumWindowsEvent(LVUserEventRef *value);
//用於呼叫dll內EnumerateWindows
void __declspec(dllexport) __cdecl EnumerateWindows(void);
實作這兩個函數與callback函數就完成dll的部分。
MgErr __declspec(dllexport) __cdecl
RegisterEnumWindowsEvent(LVUserEventRef *value)
{
//用於紀錄LabVIEW程式內Event的位址
EnumWindowsEvent = *value;
return 1;
}
void __declspec(dllexport) __cdecl EnumerateWindows(void)
{
//透過dll呼叫EnumWindows,並傳入dll內宣告的callback函數位址。
EnumWindows(EnumWindowsProc,
NULL);
}
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
char
class_name[STRING_LENGHT];
char title[STRING_LENGHT];
StrRec returnData;
// init labview string
returnData.Str1=(LStrHandle)DSNewHandle(sizeof(int32)+STRING_LENGHT*sizeof(uChar));
returnData.Str2=(LStrHandle)DSNewHandle(sizeof(int32)+STRING_LENGHT*sizeof(uChar));
// get windows class and
title data
GetClassName(hwnd,class_name,
sizeof(class_name));
GetWindowText(hwnd,title,sizeof(title));
// convert char arr to
labview string
PopulateStringHandle(returnData.Str1,class_name);
PopulateStringHandle(returnData.Str2,title);
// use labview event to
send back data
PostLVUserEvent(EnumWindowsEvent,(void
*)&returnData);
return TRUE;
}
LabVIEW程式的部分主要就是dll的呼叫與User Event的註冊,這邊就直接看圖說故事了
執行後的畫面如下,可以列舉到記事本的類字串與視窗字串:
您好不好意思我在使用您給的檔案時發現userevent.dll時找不到了RegisterEnumWindowsEvent 、EnumerateWindows這兩個function name
回覆刪除Library path是正確的
請問您知道該怎麼解決嗎?