共通コントロール(comctl32.dll)のバージョン6.0では、古いバージョンのWindowsでは使用できないコントロールをサブクラス化するための新しいアプローチが実装されています。どちらのバージョンの共通コントロールライブラリをサポートするシステムでも動作するように、サブクラス化を実装する最善の方法は何ですか?win32コントロールをサブクラス化し、古いバージョンのcomctl32.dllとの互換性を維持するにはどうすればよいですか?
答えて
最初に、バージョン6.0とそれ以前のバージョンの間のコントロールのサブクラス化で発生した変更について説明しているarticle on MSDNがあります。
下位互換性を維持する最も良い方法は、コントロールをサブクラス化するためのラッパー関数を作成することです。これには、comctl32.dllのバージョン6のコントロールをサブクラス化するために必要な関数を動的にロードする必要があります。これはどのように行うことができるかの大まかな例です。
typedef BOOL (WINAPI *LPFN_SETWINDOWSUBCLASS)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
typedef LRESULT (WINAPI *LPFN_DEFSUBCLASSPROC)(HWND, UINT, WPARAM, LPARAM);
typedef BOOL (WINAPI *LPFN_REMOVEWINDOWSUBCLASS)(HWND, SUBCLASSPROC, UINT_PTR);
typedef BOOL (WINAPI *LPFN_INITCOMMONCONTROLSEX)(LPINITCOMMONCONTROLSEX);
typedef struct SubclassStruct {
WNDPROC Proc;
} SubclassStruct;
LPFN_SETWINDOWSUBCLASS SetWindowSubclassPtr = NULL;
LPFN_REMOVEWINDOWSUBCLASS RemoveWindowSubclassPtr = NULL;
LPFN_DEFSUBCLASSPROC DefSubclassProcPtr = NULL;
LPFN_INITCOMMONCONTROLSEX InitCommonControlsExPtr = NULL;
HMODULE ComCtlModule = NULL;
int Subclasser_Init(void)
{
INITCOMMONCONTROLSEX CommonCtrlEx = {0};
ComCtlModule = LoadLibrary("comctl32.dll");
if (ComCtlModule == NULL)
return FALSE;
SetWindowSubclassPtr = (LPFN_SETWINDOWSUBCLASS)GetProcAddress(ComCtlModule, "SetWindowSubclass");
RemoveWindowSubclassPtr = (LPFN_REMOVEWINDOWSUBCLASS)GetProcAddress(ComCtlModule, "RemoveWindowSubclass");
DefSubclassProcPtr = (LPFN_DEFSUBCLASSPROC)GetProcAddress(ComCtlModule, "DefSubclassProc");
InitCommonControlsExPtr = (LPFN_INITCOMMONCONTROLSEX)GetProcAddress(ComCtlModule, "InitCommonControlsEx");
if (InitCommonControlsExPtr != NULL)
{
CommonCtrlEx.dwSize = sizeof(CommonCtrlEx);
InitCommonControlsExPtr(&CommonCtrlEx);
}
return TRUE;
}
int Subclasser_Uninit(void)
{
if (ComCtlModule != NULL)
FreeLibrary(ComCtlModule);
return TRUE;
}
LRESULT CALLBACK Subclasser_SharedSubclassProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam, UINT_PTR SubclassId, DWORD_PTR RefData)
{
SubclassStruct *Subclass = (SubclassStruct *)SubclassId;
return CallWindowProc(Subclass->Proc, hWnd, Message, wParam, lParam);
}
int Subclasser_SetProc(HWND hWnd, WNDPROC Proc, WNDPROC *OriginalProc, void *Param)
{
SubclassStruct *Subclass = NULL;
int Result = TRUE;
SetLastError(0);
if (SetWindowLongPtr(hWnd, GWLP_USERDATA, (__int3264)(UINT_PTR)Param) == 0)
{
if (GetLastError() > 0)
return FALSE;
}
if (SetWindowSubclassPtr!= NULL)
{
Subclass = (SubclassStruct*)malloc(sizeof(SubclassStruct));
Subclass->Proc = Proc;
*OriginalProc = (WNDPROC)Subclass;
Result = SetWindowSubclassPtr(hWnd, Subclasser_SharedSubclassProc, (UINT_PTR)Subclass, NULL);
}
else
{
*OriginalProc = (WNDPROC)(void *)GetWindowLongPtr(hWnd, GWLP_WNDPROC);
SetLastError(0);
if (SetWindowLongPtr(hWnd, GWLP_WNDPROC, (__int3264)(intptr)Proc) == 0)
{
if (GetLastError() > 0)
Result = FALSE;
}
}
if (Result == FALSE)
return FALSE;
return TRUE;
}
int Subclasser_UnsetProc(HWND hWnd, WNDPROC Proc, WNDPROC *OriginalProc)
{
SubclassStruct *Subclass = NULL;
int Result = TRUE;
if (RemoveWindowSubclassPtr != NULL)
{
if (*OriginalProc != NULL)
{
Subclass = (SubclassStruct *)*OriginalProc;
Proc = Subclass->Proc;
}
Result = RemoveWindowSubclassPtr(hWnd, Subclasser_SharedSubclassProc, (UINT_PTR)Subclass);
free(Subclass);
}
else
{
SetLastError(0);
if (SetWindowLongPtr(hWnd, GWLP_WNDPROC, (__int3264)(UINT_PTR)*OriginalProc) == 0)
{
if (GetLastError() > 0)
Result = FALSE;
}
}
SetLastError(0);
if (SetWindowLongPtr(hWnd, GWLP_USERDATA, 0) == 0)
{
if (GetLastError() > 0)
Result = FALSE;
}
*OriginalProc = NULL;
if (Result == FALSE)
return FALSE;
return TRUE;
}
LRESULT Subclasser_DefProc(WNDPROC OriginalProc, HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
if (OriginalProc == NULL)
return DefWindowProc(hWnd, Message, wParam, lParam);
if (DefSubclassProcPtr != NULL)
return DefSubclassProcPtr(hWnd, Message, wParam, lParam);
return CallWindowProc(OriginalProc, hWnd, Message, wParam, lParam);
}
他の唯一の例は、OpenJDKです。その欠点の1つは、同じWindowProc関数を持つダイアログ上に複数のコントロールをサブクラス化する場合にクラッシュするサブクラスIDとしてWindowProcを使用することです。上記の例では、SubclassStructという新しいメモリ構造体を割り当て、そのアドレスをサブクラスIDとして渡して、サブクラス化するコントロールの各インスタンスに一意のサブクラスIDを持たせるようにしています。
複数のアプリケーションでサブクラス関数を使用している場合、comctl32.dll <を使用するものと、comctl32.dll> = 6を使用するものがあります。comctl32を取得することによって読み込まれた共通コントロールライブラリのバージョンを検出できます。 DLLのファイルバージョン情報。これは、GetModuleFileName
とGetFileVersionInfo
を使用して行うことができます。また
、あなたが Writing Windows Custom Controlsに、次の博士ドブスの記事のように、comctl32.dllが6.0とサブクラスのコールバックにSetWindowWord/GetWindowWordを使用した場合、その後、あなたはときのcomctl32.dll条件付きで、それらのコードブロックを使用する必要があります< 6、バージョン6以上では動作しないため、アプリケーションがクラッシュする可能性があるためです。
- 1. firefoxプラグインを将来のリリースと互換性を持たせるにはどうすればいいですか
- 2. iOS5アプリケーションをiOS4と下位互換性を持たせるにはどうすればよいですか?
- 3. トーチと他の古いバージョンの互換性の問題
- 4. これらの互換性のないタイプを回避するにはどうすればよいですか?
- 5. iOS v1.3とXcode 4.2との互換性をテストするにはどうすればよいですか?
- 6. SlickgridのTextCellEditorをサブクラス化するにはどうすればよいですか?
- 7. ノードと互換性のあるCSSルールを取得するにはどうすればよいですか?
- 8. iOS 3.1と互換性のあるthree20を作成するにはどうすればよいですか?
- 9. Win32とWinCEの両方にアンマネージC++ DLLを開発するにはどうすればよいですか?
- 10. ビルドコマンドをサブクラス化するにはどうすればよいですか?
- 11. 拡張機能のFF 3.6互換バージョンを作成するにはどうすればよいですか?
- 12. Entity Framework 4.3でモデルの互換性チェックを無効にするにはどうすればよいですか?
- 13. 互換性パッケージを使用してDialogFragmentを表示するにはどうすればよいですか?
- 14. 古いバージョンのライブラリに対して/ make/configureを設定するにはどうすればよいですか?
- 15. このJavascriptライブラリの互換性を改善するにはどうすればよいですか?
- 16. 互換性ライブラリのListFragmentでProgressBarスタイルを変更するにはどうすればよいですか?
- 17. ブラウザ間での互換性を確認するにはどうすればよいですか?
- 18. 古いバージョンのマシンで新しいバージョンのDLLを使用するには?
- 19. 2012年にIE8との互換性を維持することの重要性は何ですか?
- 20. 古いバージョンのJavaをサポートする.javaをコンパイルするにはどうすればよいですか?
- 21. 古いAndroidバージョンでFragmentsとobjectAnimatorを使用するにはどうすればよいですか?
- 22. Webアプリケーションの互換性をテストするにはどうすればよいですか?
- 23. Matlabのバージョンとの互換性をチェックするツールですか?
- 24. RTSPセッションを維持するにはどうすればいいですか?
- 25. 古いバージョンのファイルを強制的に破棄するにはどうすればよいですか?
- 26. Win32 DLLを参照するアセンブリをロードするにはどうすればよいですか?
- 27. OpenSocial Win32の互換性
- 28. Fabric.jsオブジェクトクラスを変更して、すべてのサブクラスが新しいカスタム属性を持つようにするにはどうすればよいですか?
- 29. 製品リリースではライブラリ名が変更され、古いものと新しいものとの互換性はどのようになっていますか?
- 30. より古いjavascriptとInternet Explorer 8との互換性
Windowsマシンの0.15%にはこのようなコードが必要です。その所有者はソフトウェアを購入していない。 –
[SetWindowSubclass'のドキュメント(http://msdn.microsoft.com/en-us/library/windows/desktop/bb762102.aspx)によれば、その関数はComctl32.dll、バージョン5.8以降で使用できます。それは間違っていますか?これは実際にv6にオプトインする必要はありませんか? (私は遠くまで覚えていません) –
Windows 95-2000をターゲットにしている場合、その機能は利用できなくなります。 –