Domanda

Sto creando un filo conduttore che cerca di una finestra. Quando trova la finestra, si sostituisce la sua WindowProc e gestisce WM_COMMAND e WM_CLOSE.

Ecco il codice che cerca la finestra e le sottoclassi che:

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());
   }
}

E il 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);
}        

Tutto questo funziona bene in condizioni normali. Ma sto vedendo due istanze di cattivo comportamento in ordine di cattiveria:

  1. Se non si chiude la finestra di dialogo in un minuto o poco più, l'applicazione si blocca. È questo perché il filo si sta garbage collection? Questo tipo di senso, per quanto GC può dire il filo è fatto? Se questo è il caso, (e non so che sia), come posso fare il filo rimanere intorno fino a quando la finestra di dialogo è di circa?

  2. Se ho subito chiudere la finestra con il tasto 'X' (WM_CLOSE) l'applicazione si blocca. Credo che il suo fragore nel WindowProc, ma non riesco a ottenere un punto di interruzione in là. Ricevo un AccessViolationException, L'eccezione dice: "Tentativo di lettura o scrittura della memoria protetta. Ciò è spesso un'indicazione che l'altra memoria è danneggiata." La sua una condizione di competizione, ma di ciò che non lo so. Cordiali saluti, ero stato resettare il vecchio WindowProc una volta ho elaborato i comandi, ma che stava arrestando anche più spesso!

Tutte le idee su come posso risolvere questi problemi?

È stato utile?

Soluzione 2

Infine si avvicinò con una soluzione, attaccando il problema da una diversa angolazione. Sono stato in grado di impostare un hook al livello di sistema nel codice gestito utilizzando SetWinEventHook, e l'opzione WINEVENT_OUTOFCONTEXT, che ha sorprendentemente proprietà: La funzione di richiamata non è mappato nello spazio di indirizzi del processo che genera l'evento. Ho intrappolare l'EVENT_SYSTEM_DIALOGSTART evento di ricevere notifiche ogni volta che viene creata una finestra di dialogo, e quando il suo EVENT_SYSTEM_DIALOGEND distrutti.

Altri suggerimenti

Due punti di osservazione che posso fare ....

  • Nella tua DetectFileDialogProc, si confrontano wnd su null, che è un tipo di IntPtr sì? in caso affermativo, che di controllo per il confronto dovrebbe essere if (wnd > IntPtr.Zero){ .... }
  • Nella tua WndProc, si utilizza la variabile this per la lock che è una brutta cosa da fare ... si dovrebbe fare qualcosa di simile private readonly object objLock = new object(); ed entro l'utilizzo WndProc questo lock (objLock){....}

e vedere se questo risolve il problema ....

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top