Thema: Delphi NM_RETURN - Problem

Einzelnen Beitrag anzeigen

Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#32

Re: NM_RETURN - Problem

  Alt 3. Mai 2007, 11:55
hi

es scheint, dass das NM_RETURN Problem noch keiner gelöst hat?

Hier das Problem:

Das Problem ist, dass die Enter Taste, oder allgemein alle Tasten, im Dialog von einem ListView (oder anderen Elementen) nicht über die Nachricht WM_NOTIFY empfangen werden kann.

Dasselbe funktioniert jedoch, wenn man das ListView NICHT in einem Dialog hat.

Hier die Lösung :

Es liegt an IsDialogMessage, welche die eingehenden Nachrichten bearbeitet und bestimmte Tasten nicht an die Elemente (Listview) weitergibt. Die Tab-Taste wird dort z.B. verwendet, um zum nächsten Element zu springen.
Die Enter-Taste ist in Dialogen eine besondere Taste (genauso wie ESC), welche ein ID_OK repräsentiert. Also ein Klicken auf den OK-Button.
Daher empfängt kein anderes Steuerelement diese Tasten.

Es gibt drei Lösungen:

Wer IsDialogMessage selbst aufruft, der kann vorher einfach die Nachricht vorher schon abfangen,
und die Nachricht an das eigene Fenster schicken.


Delphi-Quellcode:
BOOL PreTranslateMessage(MSG* pMsg)
   {
      switch (pMsg->message)
      {
      case WM_KEYDOWN:
         {
            switch (pMsg->wParam)
            {
               case VK_RETURN:
               case VK_F5:
                  SendMessage(myWindowHandle, pMsg->message,pMsg->wParam,pMsg->lParam);
                  return FALSE;
            }

         }
      }
      
      return ::IsDialogMessage(m_hWnd, pMsg);
   }
(Sorry für C++ Code, aber es sollte klar werden.)


Die zweite Lösung ist, dass man von der Listview Klasse eine eigene Ableitung erstellt (Subclassing)
und dort die WindowProc überschreibt.
Es geht jedoch auch einfach so, dass man CreateWindow verwendet und in der Struktur, die WndProc
auf eine eigene Version setzt.

Das Ziel ist es dabei, die Nachricht WM_GETDLGCODE, die von IsDialogMessage an jedes einzelne Steuerelement
gesendet wird, abzufangen und einen besonderen Rückgabewert zu erzeugen:

GetDlgCode: http://msdn2.microsoft.com/en-us/library/ms645425.aspx
The Old new Thing Blog: http://blogs.msdn.com/oldnewthing/ar.../26/55872.aspx
MSDN sagt dazu: http://support.microsoft.com/kb/83302/de

Delphi-Quellcode:
LRESULT CALLBACK ListViewControlWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
   {
      switch (message)
      {
      case WM_GETDLGCODE:
         switch (wParam)
         {
         case VK_F5:
         case VK_RETURN:
            return DLGC_WANTALLKEYS | DLGC_WANTMESSAGE;
         }

      }
      
         return ::DefWindowProc(hwnd, message, wParam, lParam);
}

Die dritte Lösung ist, die WindowProc eines existierenden ListViews zu verbiegen:



Delphi-Quellcode:
//Die Listview WindowProc verbiegen, damit man die Enter-Taste abfragen können,
//weil diese von IsDialogMessage verbogen wird
LPARAM wndProc = GetWindowLong(mListViewHandle GWL_WNDPROC);
SetWindowLong(mListViewHandle,GWLP_USERDATA,(LPARAM)wndProc);
SetWindowLong(mListViewHandle, GWL_WNDPROC,(LPARAM)&ListViewControlWndProc);

Delphi-Quellcode:
LRESULT CALLBACK ListViewControlWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   switch (message)
   {
   case WM_GETDLGCODE:
      switch (wParam)
      {
      case VK_F5:
      case VK_RETURN:
         return DLGC_WANTALLKEYS | DLGC_WANTMESSAGE;
      }

   }
   

        LPARAM l = ::GetWindowLong(hwnd,GWL_USERDATA);
   WNDPROC wndProc = (WNDPROC)l;

   if (wndProc)
     return wndProc(hwnd,message,wParam,lParam);
   
}

Wer Lust hat von den Mods kann den C++ Code nach Delphi portieren. Sorry aber ich hab grad kaum Zeit
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  Mit Zitat antworten Zitat