📄 article1.htm
字号:
usesgetlasterror,
entry("GetWindowsDirectoryA"),
#else
entry("GetWindowsDirectory"),
#endif
helpstring("Gets Windows directory"),
]
UINT WINAPI GetWindowsDirectory([in, out] LPSTR lpszSysPath,
[in] UINT cbSysPath);
</FONT></PRE><P>For most string functions, the <i>entry </i>name must use the ANSI or Unicode™ name that actually appears in the DLL. In other words, <i>entry </i>is equivalent to the Alias attribute in a <b>Declare</b> statement. The name in the prototype is the one that you use in your Basic source code.
<P>The LPSTR type and its Unicode cousin, LPWSTR, are specifically recognized by ODL, although they are essentially equivalent to char * and wchar_t * in C++. It is possible to write Unicode function entries for Visual Basic, but this version of my type library doesn't attempt to do so. It always uses LPSTR rather than LPWSTR. The LPCSTR type represents a constant string in C++, but inasmuch as ODL doesn't recognize the <i>const</i> modifier, LPCSTR is just a preprocessor <b>#define</b> for LPSTR. ODL also recognizes the BSTR type, but we won't use it in this article.<P>
<h3>Pointer and Array Parameters</h3><P>Functions use pointers when they need to return more than one parameter or to return data in structures or arrays. Normally you pass in an empty variable and the function fills it with a value. <b>GetScrollRange</b> is a classic example. Its <b>Declare</b> statement looks like this:
<P><PRE><FONT FACE="COURIER" SIZE="2">Declare Function GetScrollRange Lib "USER32" ( _
ByVal hWnd As Long, ByVal nBar As Long,
lpMin As Long, lpMax As Long) As Long
</FONT></PRE><P>The <i>lpMin </i>and <i>lpMax </i>parameters are passed by reference so that they can receive the results. The ODL version looks like this: <P><PRE><FONT FACE="COURIER" SIZE="2"> [
usesgetlasterror,
entry("GetScrollRange"),
helpstring("Gets the minimum and maximum positions of a scroll bar"),
]
void WINAPI GetScrollRange([in] HWND hwnd, [in] int fnBar,
[out] int FAR * lpnMinPos,
[out] int FAR * lpnMaxPos);
</FONT></PRE><P>The FAR statement is a leftover from the bad old days. In 32-bit code it's simply a blank <b>define</b> that will be ignored. The <i>[out]</i> attribute indicates that the input value (if any) will be ignored and an output value will be written to the parameter. <P>To an API function, an array parameter is simply a pointer to a variable that happens to have several more variables of the same type next to it in memory. The <i>lpMin </i>and <i>lpMax </i>parameters above are simply one-member arrays. The API convention is to pass the number of elements in the array in a separate parameter. <P>Here's an ODL entry for the <b>SetSysColor</b> function, which takes two array parameters: <P><PRE><FONT FACE="COURIER" SIZE="2"> [
usesgetlasterror,
entry("SetSysColor"),
helpstring("Sets colors of the display element..."),
]
void WINAPI SetSysColors([in] int cElements,
[in] int FAR * lpaElements,
[in] COLORREF FAR * lpaRgbValues);
</FONT></PRE><P>Like most API array functions, this one has a separate parameter, <i>cElements</i>,<i> </i>to indicate the number of elements in the array (or arrays, in this case). The <i>lpaElements </i>parameter is an array of constants indicating display elements to be modified, and <i>lpaRgbValues </i>indicates the new colors for each corresponding index. <P>Don't confuse API arrays with Basic arrays, which are actually OLE safe arrays. They work very differently, as we'll see in Article 5. <P><blockquote><b>Note:</b> This entry also illustrates one of the more unpleasant aspects of the ODL syntax. Helpstring entries must fit on one line. If you look up <b>SetSysColors</b> in USER.ODL, you'll see that the real help description is almost 120 characters wide, and many other help strings are even wider. ODL authors must bear the same handicap Visual Basic programmers had to put up with until version 4.0--lack of a line continuation character. Object Browsers such as the one in Visual Basic normally perform automatic word wrapping, so it doesn't matter how long you make your helpstrings. But the single-line limitation does make it hard to read your own source code, and even more difficult to display code in articles like this one. Furthermore, the text editor you use to edit ODL files may have a line length limitation. Fortunately, Microsoft Developer Studio doesn't have such a limitation--or at least not one that I had the patience to exceed when I tried typing a line longer than 500 characters. </blockquote><P><h3>Typeless Parameters</h3><P>The <b>SendMessage</b> function is a classic example of the typeless parameter. Here are a couple of 32-bit Basic <b>Declare</b> statements for it: <P><PRE><FONT FACE="COURIER" SIZE="2">Declare Function SendMessage Lib "USER32" Alias "SendMessageA" ( _
ByVal hWnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, ByVal lParam As Any) As Long
Declare Function SendMessageByRef Lib "USER32" Alias "SendMessageA" ( _
ByVal hWnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, lParam As Any) As Long
</FONT></PRE><P>The <i>lParam </i>argument can be almost any type, depending on what message you are sending. Sometimes you send data by value in a Long. Sometimes you send a string (a pointer to characters in C++). Sometimes you send a pointer to data in a structure, array, or other variable. The declarations above allow you to pass any kind of data either by value or by reference. Actually, you could get by with only the second definition if you were willing to give the ByVal keyword in the Basic call, rather than in the declaration, whenever you wanted to pass something by value. <P>But you can't declare either of these in a type library because ODL has no equivalent of the As Any statement. A C++ programmer might guess that <i>void * </i>would be equivalent to As Any, but unfortunately it doesn't work that way. You can indeed define a parameter as <i>void * </i>in ODL, but Visual Basic won't have a clue what you're talking about. <P>That doesn't mean you can't define <b>SendMessage</b>. It just means you'll have to define a group of aliased <b>SendMessage</b> functions such as these:<P><PRE><FONT FACE="COURIER" SIZE="2"> [
#ifdef WIN32
usesgetlasterror,
entry("SendMessageA"),
#else
entry("SendMessage"),
#endif
helpstring("Sends a Windows message (LPARAM as String)")
]
LRESULT WINAPI SendMessageAsStr([in] HWND hwnd, [in] UINT uMsg,
[in] WPARAM wParam,
[in, out] LPSTR lParam);
[
#ifdef WIN32
usesgetlasterror,
entry("SendMessageA"),
#else
entry("SendMessage"),
#endif
helpstring("Sends a Windows message (LPARAM as Long pointer)")
]
LRESULT WINAPI SendMessageAsLp([in] HWND hwnd, [in] UINT uMsg,
[in] WPARAM wParam,
[in] LONG lParam);
[
#ifdef WIN32
usesgetlasterror,
entry("SendMessageA"),
#else
entry("SendMessage"),
#endif
helpstring("Sends a Windows message (LPARAM as ByRef Long or Long array)")
]
LRESULT WINAPI SendMessageForLong([in] HWND hwnd, [in] UINT uMsg,
[in] WPARAM wParam,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -