Crear subclases de una ventana de un hilo en c #
-
22-09-2019 - |
Pregunta
Estoy creando un hilo que busca una ventana. Cuando encuentra la ventana, se anula su WindowProc, y las manijas WM_COMMAND y WM_CLOSE.
Este es el código que busca la ventana y subclases que:
public void DetectFileDialogProc()
{
Window fileDialog = null;
// try to find the dialog twice, with a delay of 500 ms each time
for (int attempts = 0; fileDialog == null && attempts < 2; attempts++)
{
// FindDialogs enumerates all windows of class #32770 via an EnumWindowProc
foreach (Window wnd in FindDialogs(500))
{
IntPtr parent = NativeMethods.User32.GetParent(wnd.Handle);
if (parent != IntPtr.Zero)
{
// we're looking for a dialog whose parent is a dialog as well
Window parentWindow = new Window(parent);
if (parentWindow.ClassName == NativeMethods.SystemWindowClasses.Dialog)
{
fileDialog = wnd;
break;
}
}
}
}
// if we found the dialog
if (fileDialog != null)
{
OldWinProc = NativeMethods.User32.GetWindowLong(fileDialog.Handle, NativeMethods.GWL_WNDPROC);
NativeMethods.User32.SetWindowLong(fileDialog.Handle, NativeMethods.GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(new WindowProc(WndProc)).ToInt32());
}
}
Y el WindowProc:
public IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
lock (this)
{
if (!handled)
{
if (msg == NativeMethods.WM_COMMAND || msg == NativeMethods.WM_CLOSE)
{
// adding to a list. i never access the window via the hwnd from this list, i just treat it as a number
_addDescriptor(hWnd);
handled = true;
}
}
}
return NativeMethods.User32.CallWindowProc(OldWinProc, hWnd, msg, wParam, lParam);
}
Todo esto funciona bien en condiciones normales. Pero yo estoy viendo dos casos de mal comportamiento con el fin de maldad:
-
Si no lo hago cerrar el diálogo dentro de un minuto más o menos, la aplicación se bloquea. ¿Esto es porque el hilo se está recolector de basura? Esto tipo de sentido esto, en lo que GC puede decir el hilo se hace? Si este es el caso, (y no sé que es), ¿cómo puedo hacer que la estancia hilo alrededor siempre y cuando el diálogo es de alrededor?
-
Si yo inmediatamente cerrar el diálogo con el botón 'X' (WM_CLOSE) la aplicación se bloquea. Creo que su estrellarse en el WindowProc, pero no puedo conseguir un punto de interrupción en ese país. Recibo un AccessViolationException, La excepción dice "Intento de leer o escribir en la memoria protegida. Esto es a menudo una indicación de que otra memoria está dañada." Su condición de una carrera, pero de lo que no sé. Para su información, que había sido el restablecimiento del antiguo WindowProc vez Procesé los comandos, pero que estaba fallando incluso más a menudo!
¿Alguna idea sobre cómo puedo resolver estos problemas?
Solución 2
Finalmente se le ocurrió una solución, atacando el problema desde un ángulo diferente. Yo era capaz de establecer un enlace de todo el sistema en código administrado utilizando SetWinEventHook, y la opción WINEVENT_OUTOFCONTEXT, que sorprendentemente tiene la propiedad: La función de devolución de llamada no está asignada al espacio de direcciones del proceso que genera el evento. Me trampa de la EVENT_SYSTEM_DIALOGSTART evento para recibir notificaciones cada vez que se crea un cuadro de diálogo, y cuando su EVENT_SYSTEM_DIALOGEND destruidos.
Otros consejos
Dos puntos de observación que puedo hacer ....
- En su
DetectFileDialogProc
, que está comparandownd
a nulo, que es un tipoIntPtr
sí? si es así, que el registro para la comparación debe serif (wnd > IntPtr.Zero){ .... }
- En su
WndProc
, está utilizando la variablethis
para lalock
que es un mal que hay que hacer ... que debe hacer algo como estoprivate readonly object objLock = new object();
y dentro de su utilizaciónWndProc
estelock (objLock){....}
y ver si se soluciona el problema ....