2

まず、SendMessageTimeout のドキュメント:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644952%28v=vs.85%29.aspx

この C++ コードがあり、C# に変換したい:

LRESULT success = SendMessageTimeout(
    HWND_BROADCAST,
    WM_SETTINGCHANGE,
    0,
    (LPARAM) "Environment",
    SMTO_ABORTIFHUNG,
    5000,
    NULL
);

私がC#でやったこと:

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern IntPtr SendMessageTimeout(
        IntPtr hWnd,
        uint Msg,
        UIntPtr wParam,
        IntPtr lParam,
        uint fuFlags,
        uint uTimeout,
        out UIntPtr lpdwResult
    );

    SendMessageTimeout(
        (IntPtr)0xFFFFFFFF,    //HWND_BROADCAST
        0x001A,                //WM_SETTINGCHANGE
        (UIntPtr)0,
        (IntPtr)"Environment", // ERROR_1: can't convert string to IntPtr
        0x0002,                // SMTO_ABORTIFHUNG
        5000,
        out UIntPtr.Zero       // ERROR_2: a static readonly field can not be passed ref or out
    );
4

2 に答える 2

5

あなたの問題のために。

  1. HWND_BROADCASTはあり0xFFFFません0xFFFFFFFF
  2. Marshal.StringToHGlobalUniを使用して LPARAM 値のメモリを手動で割り当て 、呼び出し後にMarshal.FreeHGlobalを使用してメモリを解放する必要があります。このメモリを解放する必要があります。そうしないと、メモリがリークします。マーシャルされたメモリはガベージ コレクションされません。
  3. lpdwResult変数を作成して渡すだけです。そのIntPtr値は無視できます。

コードは次のようになります。

IntPtr result = IntPtr.Zero;
IntPtr setting = Marshal.StringToHGlobalUni("Environment");

SendMessageTimeout(
    (IntPtr)0xFFFF,        //HWND_BROADCAST
    0x001A,                //WM_SETTINGCHANGE
    (UIntPtr)0,
    (IntPtr)setting,
    0x0002,                // SMTO_ABORTIFHUNG
    5000,
    out result
);

Marshal.FreeHGlobal(setting);

一般に、呼び出しに渡すメモリを解放するときは注意が必要ですSendMessage。これは、受け取ったウィンドウが渡したポインターで何をするかわからないためです。ただしWM_SETTINGCHANGE、組み込みの Windows メッセージであるため、Windows がこのポインターを処理します。

于 2013-11-01T23:45:03.750 に答える