Obecna deklaracja SendMessage na co PInvoke.net jest:
[DllImport(user32.dll, CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(HandleRef hWnd, uint Msg,
IntPtr wParam, IntPtr lParam);
Uwaga: HWND nie jest już IntPtr i został zastąpiony HandleRef . Bardzo luźna wyjaśnienie zmian jest podana:
Można zastąpić „hWnd” z „IntPtr” zamiast „HandleRef”. Jednak pacjent przyjmuje ryzyko w ten sposób - może to spowodować awarię kod z warunków wyścigowych. Runtime .NET mogą i będą wyrzucać okno uchwyty spod wiadomości - powodując różnego rodzaju nieprzyjemnych problemów!
Ktoś wiki'd pytanie obserwacji:
Pytanie: Nie mogę ten ostatni problem można rozwiązać za pomocą Organizowanie, specjalnie przypinanie?
I ktoś odpowiedział:
Odpowiedź: Można użyć GC.KeepAlive () zaraz po SendMessage () z obiektu formularza jako parametr keepalive ().
Wszystko to „rozstrzygających swoją formę pod tobą” wydaje się dziwne dla mnie. SendMessage jest synchroniczne wywołanie. To nie wróci aż do momentu wysłana wiadomość została przetworzona.
Konsekwencją jest to, że wtedy uchwyt forma może zostać zniszczona w dowolnym czasie. Na przykład:
private void DoStuff()
{
//get the handle
IntPtr myHwnd = this.Handle;
//Is the handle still valid to use?
DoSomethingWithTheHandle(myHwnd); //handle might not be valid???
//fall off the function
}
Oznacza to, że uchwyt okna mogą stać się nieważne pomiędzy czasem używam go a czas metoda kończy?
aktualizacja One
rozumiem pojęcia, że kiedyś to forma wykracza poza zakres, to uchwyt jest nieprawidłowy. na przykład:
private IntPtr theHandle = IntPtr.Zero;
private void DoStuff()
{
MyForm frm = new MyForm())
theHandle = frm.Handle;
//Note i didn't dispose of the form.
//But since it will be unreferenced once this method ends
//it will get garbage collected,
//making the handle invalid
}
Jest dla mnie oczywiste, że uchwyt formie nie jest ważna po powrócił DoStuff. To samo byłoby prawdą, bez względu na technikę - jeśli formularz nie jest utrzymywana w pewnym zakresie, to nie jest ważne, aby użyć.
chciałbym zgadzam się z (brak łącza guy) tym, że forma będzie trzymać się aż wszystkie komunikaty wysyłane zostały otrzymane. CLR nie wie, kto może nadano uchwyt okna mojego formularza, a nie ma możliwości dowiedzenia się, kto może zadzwonić SendMessage () w przyszłości.
Innymi słowy, nie mogę sobie wyobrazić, że powołanie:
IntPtr hWnd = this.Handle;
będzie teraz zapobiec tego przed śmieci zebrane.
aktualizacja Two
Nie mogę sobie wyobrazić okno obsłużyć około zachowa formę przed śmieci zebrane. to znaczy:
Clipboard.AsText = this.Handle.ToString();
IntPtr theHandle = (IntPtr)(int)Clipboard.AsText;
Odpowiedź
Ale to są illevant punktów - oryginalne pytanie nadal jest:
Można runtime rozporządzania uchwyt w formie spod mnie?
Odpowiedź, jak się okazuje, nie jest. Środowisko wykonawcze nie będą wyrzucać formie spod mnie. To będzie likwidować przypisań formie - ale bez odnośników formy nie są pode mną. „Pod Me” oznacza, że mają odniesienie do formy.
Z drugiej strony, podkreślając uchwyt okna Okna obiektu formularza można zniszczyć spod mnie (i naprawdę, jak to może nie - klamki okienne są liczone należy odwoływać - nie powinny one być):
IntPtr hwnd = this.Handle;
this.RightToLeft = RightToLeft.Yes;
//hwnd is now invalid
Ważne jest również, aby pamiętać, że HandleRef nie pomoże uniknąć problemów spowodowanych przez tworzenie owijarki obiekt wokół okna Windows obsługuje:
Powód 1 Jeśli obiekt forma jest zniszczona, ponieważ nie mają odniesienia do niej - to jesteś po prostu głupi, próbując rozmawiać z postaci, która przez prawa nie powinny już istnieć. Tylko dlatego, że GC nie ma zdobyć wokół niej jeszcze nie sprawi, że mądry - to sprawia, że jesteś szczęśliwy. HandleRef jest hack zachować odniesienie do formularza. Zamiast używać:
HandleRef hr = new HandleRef(this, this.Handle);
DoSomethingWithHandle(this.Handle);
można łatwo używać:
Object o = this;
DoSomethingWithHandle(this.Handle);
Powód 2 HandleRef nie przeszkodzi formę z ponownego tworzenia to uchwyt okna bazowego, np:
HandleRef hr = new HandleRef(this, this.Handle);
this.RightToLeft = RightToLeft.Yes;
//hr.Hande is now invalid
Tak więc, podczas gdy oryginalny modyfikator SendMessage P / Invoke nie podkreślić problem, jego rozwiązanie nie jest rozwiązaniem.