[英]How do I get the length of a window class name so I know how large of a buffer to allocate?
如何預先獲取類名長度,以便將其傳遞給GetClassName()
函數中的nMaxCount
參數? 像控件存在的WM_GETTEXTLENGTH
消息或者窗口類名是否定義了固定的大小限制? 如果是的話,這個價值是多少?
我的目標是傳遞確切的大小而不是重新分配方法(調用GetClassName()
直到它返回小於其緩沖區的大小)。
我當前的實現(沒有重新分配方法):
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
string GetWindowClass(IntPtr hWnd)
{
const int size = 256;
StringBuilder buffer = new StringBuilder(size + 1);
if (GetClassName(hWnd, buffer, size) == 0)
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
return buffer.ToString();
}
對於此特定函數,類名限制為256個字符。 (請參閱WNDCLASSEX
結構的lpszClassName
成員的文檔。)因此,只需分配該大小的固定緩沖區即可完成!
為了完整起見,讓我們看一下在沒有固定大小緩沖區的情況下調用函數的更通用的解決方案。 在這種情況下,我們可以應用一個簡單的try-double-retry算法,如下所示:
您可以使用以下代碼查看算法:
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern int GetClassNameW(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
string GetWindowClass(IntPtr hWnd)
{
string className = String.Empty;
int length = 10; // deliberately small so you can
// see the algorithm iterate several times.
StringBuilder sb = new StringBuilder(length);
while (length < 1024)
{
int cchClassNameLength = GetClassNameW(hWnd, sb, length);
if (cchClassNameLength == 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
else if (cchClassNameLength < length - 1) // -1 for null terminator
{
className = sb.ToString();
break;
}
else length *= 2;
}
return className;
}
(設置一個斷點並逐步實際看到它的實際效果。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.