0

WM_SETTEXT古い学校の Win32 API を介して別のウィンドウのテキストを設定するために使用できるメッセージを考えてみましょう。.NET でこれを行う方法はおそらく多数ありますが、私が知っている方法は次の 2 つです。

[DllImport("USER32", EntryPoint = "SendMessage", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, string lParam);

SendMessage(handle, WM_SETTEXT, IntPtr.Zero, "Magic String");

 

[DllImport("USER32", EntryPoint = "SendMessage", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

IntPtr textPointer = Marshal.StringToCoTaskMemUni("Magic String");
SendMessage(handle, WM_SETTEXT, IntPtr.Zero, textPointer);
Marshal.FreeCoTaskMem(textPointer);

最初のものは、dll インポートの宣言で文字列を使用し、.NET にそれを処理させます。この 2 番目は を使用し、IntPtrを使用してポインタを明示的に作成し、 を使用しMarshal.StringToCoTaskMemUniて解放しMarshal.FreeCoTaskMemます。私が知る限り、これらのアプローチはどちらもうまく機能します。

私は通常、前者を実行します (実際、VB6 プログラマーとして何年も前に実行していました) が、別の StackOverflow 投稿のコメントで後者に出くわし、前者が潰す必要のある別の悪い習慣であるかどうかに興味がありました。

char[]宣言で配列を使用し、StringBuilder

私の質問は簡単です - (もしあれば) それを行う正しい方法はどれですか? たとえば、SendMessageとにかく Win32 呼び出しはポインターのみを受け入れるため、「何か」が最初のバージョンの舞台裏でポインターを作成しているに違いありません。ポインタの解放。

4

1 に答える 1

2

のパラメーターを宣言するとstring、p/invoke マーシャラーは、バックグラウンドで、null で終わる文字配列へのポインターにマーシャリングします。マーシャラーは、すべてのメモリ割り当てと割り当て解除を処理します。パラメータを使用して自分で行うこともできますがIntPtr、最終的には同じになります。

SendMessageどちらを選択するかは、送信する他のメッセージに宣言を使用する予定があるかどうかにかかっています。

  • SendMessageforのみを呼び出す場合はWM_SETTEXT、パラメーターを受け取るように宣言しstringます。
  • を使用SendMessageして他のメッセージを送信する場合は、パラメーターを宣言しIntPtrてマーシャリングを手動で実行できます。
  • さらに別のオプションは、複数のオーバーロードされたバリアントを宣言しSendMessageて、プログラマーにとって可能な限り便利なコードを呼び出すことができるようにすることです。

では、最後のオプションを取り上げましょう。WM_GETTEXTと同様に送信する必要があるとしますWM_SETTEXTWM_SETTEXTマネージドからネイティブに文字列データを渡す必要があるため、string. の場合WM_GETTEXT、ネイティブ コードがウィンドウ テキストに入力できるように、バッファを提供する必要があります。そして、それはあなたが使いたいことを意味しますStringBuilder. したがって、2 つのオーバーロードを宣言しstringますStringBuilder。には前者をWM_SETTEXT、 には後者を使用しWM_GETTEXTます。

于 2013-10-27T09:25:28.447 に答える