[c++/winAPI]Keyevent&Fenster-/Messagehandle

kickerxy123

Erfahrenes Mitglied
Hallo, ich habe ein vermutlich recht triviales Problem.
Also, ich benutze Dev-C++, win XP 32bit, Mingw.

Mein Problem liegt in der Auswertung von Key-Events. Ein einfaches Keyevent, wie WM_CHAR oder WM_KEYDOWN ist klar, z.B.
Code:
    switch (message)             
    {   
        case WM_CHAR: {
            switch (wParam) 
            {           case 0x09: 
                          SendMessage(hFortschritt, WM_SETTEXT, 0, (LPARAM)"Tab");
                          UpdateWindow(hwnd);
                          UpdateWindow(hFortschritt);
funktioniert einwandfrei, die Textbox hFortschritt gibt an: "Tab".
Allerdings: wenn ich jetzt z.B. in das erste editFeld klicke/schreibe (also das Fenster aktiviere/in den Vordergrund setze), und dann auf Tab(0x09) drücke, passiert gar nichts mehr, da ja der MessageHandler nur auf aktionen im mainwindow reagiert, so weit richtig?
Wenn ja, wie schreib ich ein Messagehandler für untergeordnete Fenster(eben z.B. hEdit). Vielleicht noch zum Deklarieren des EditFeldes:
Code:
 hEdit2 = CreateWindowEx(WS_EX_CLIENTEDGE,
                                   "edit",
                                   edit2,    // <- das ist der Inhalt des Editfelds
                                   WS_CHILD | WS_VISIBLE //|// WS_VSCROLL |//ES_MULTILINE |
                                              //ES_AUTOVSCROLL,
                                              ,
                                   120, 50, 150, 25,
                                   hwnd,
                                   NULL,
                                   ((LPCREATESTRUCT) lParam) -> hInstance,
                                   NULL);

            free(edit2);
             SendMessage(hEdit2, WM_SETTEXT, 0, (LPARAM)port_str.c_str());
und der Messagehanlder hat folgende Struktur:
Code:
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{   

    switch (message)             
    {   
        case WM_CHAR: {
            switch (wParam) 
            {
Ich hoffe ihr könnt mir helfen,
lg
kickerxy
 
Wie sieht den dein "RegisterClass()" aufruf uas? bzw, welche werte bekommt die "WNDCLASS" Struktur übergeben?
Dies ist sowohl für das Hauptfenster als auch für das "edit" fenster interessant,.
Genauso, könnte CreateWindowEx() vom Hauptfenster interessant sien.
 
Wenn du Nachrichten von Child-Fenstern haben willst, dann musst du Subclassen (einfach mal in MSDN eingeben). Die wichtigsten Nachrichten bekommst du allerdings per Notify (EN_xxx) über WM_NOTIFY oder WM_COMMAND.
 
Vielen Dank!
Ich habe mich jetzt mit dem Subclassen beschäftigt, stoße aber auf folgendes Problem:
Code:
...
#include <commctrl.h>
...//habe auch libcomctl32.a gelinkt
...
typedef LRESULT (CALLBACK *SUBCLASSPROC)(          HWND hWnd,
    UINT uMsg,
    WPARAM wParam,
    LPARAM lParam,
    UINT_PTR uIdSubclass,
    DWORD_PTR dwRefData
);
BOOL SetWindowSubclass(          HWND hWnd,
    SUBCLASSPROC pfnSubclass,
    UINT_PTR uIdSubclass,
    DWORD_PTR dwRefData
);
...
Winmain....
...
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  
    {
     case WM_CREATE:
                  
             SetWindowSubclass(hEdit2, OwnerDrawButtonProc, 0, 0);
              .......
}


LRESULT CALLBACK OwnerDrawButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam,
                               LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    switch (uMsg)
    {
    case WM_KEYDOWN:
         switch (wParam)
         {
                case VK_TAB: abort();break;
                default:break;
                }
break;
   
    } 
//   return DefSubclassProc(hWnd, uMsg, wParam, lParam);

}
Selbst ohne return DefSubclas.... kommt folgender Fehler:
[Linker error] undefined reference to `SetWindowSubclass(HWND__*, long (*)(HWND__*, unsigned int, unsigned int, long, unsigned int, unsigned long), unsigned int, unsigned long)'
...
lg
kickerxy



#edit:

der Ansatz mit EN_XXX:
klappt ganz gut, aber noch nicht richtig:
Code:
...
bool load=false;
...
CALLBACK...
switch(...){
...
         if(lParam == (LPARAM)hEdit2){
                   if(HIWORD(wParam) == EN_SETFOCUS)
                   { load=true;
                    } 
                   if(HIWORD(wParam) == EN_CHANGE)
                   {if(load==true)
                                 abort();
                   } 
         }
wie gesagt, klappt insoweit, dass er aborted, wenn ich z.B. einen Buchstaben drücke(nicht aber bei Tab!), außerdem will ich ja nicht nur wissen, dass was gechanged ist, sondern WELCHER Key gedrückt wurde (in dem Fall interessiert mich TAB).
Ich müsste also EN_CHANGE noch spezifisieren, wie?




#edit2:
wg dem Aufruf: (komplette WinMain)
Code:
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default color as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
 hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           "Server",       /* Title Text */
           WS_CAPTION,       
        //   WS_OVERLAPPEDWINDOW, /* default window */
          // CW_USEDEFAULT,       /* Windows decides the position */
           360,300,
           //CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    ShowWindow (hwnd, nFunsterStil);
    UpdateWindow(hwnd);
    while (GetMessage (&messages, NULL, 0, 0))
    {
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }
    return messages.wParam;
Code:
 hEdit2 = CreateWindowEx(WS_EX_CLIENTEDGE,
                                   "edit",
                                   edit2,    // <- das ist der Inhalt des Editfelds
                                   WS_CHILD | WS_VISIBLE //|// WS_VSCROLL |//ES_MULTILINE |
                                              //ES_AUTOVSCROLL,
                                              ,
                                   120, 50, 150, 25,
                                   hwnd,
                                   NULL,
                                   ((LPCREATESTRUCT) lParam) -> hInstance,
                                   NULL);

                   free(edit2);
                   SendMessage(hEdit2, WM_SETTEXT, 0, (LPARAM)port_str.c_str());
 
Zuletzt bearbeitet:
beim ausführen von CreateWindowEx() musst du anstatt "edit" => szClassName übergeben, oder du musst eine weitere CALLBACK - funktion mit RegisterCalssEx() anmelden, welche für wincl.lpszClassName => "edit" übergeben bekommt.
 
hm okay, wenn cih dich richtig verstanden habe:
Code:
char szClassName[ ] = "WindowsApp";
char szClassName2[ ] = "edit";

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)

{ 
                    
                    
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default color as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;
    WNDCLASSEX wincl2;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl2.hInstance = hThisInstance;
    wincl2.lpszClassName = szClassName2;
    wincl2.lpfnWndProc = Tab;      /* This function is called by windows */
    wincl2.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl2.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl2.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl2.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl2.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl2.lpszMenuName = NULL;                 /* No menu */
    wincl2.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl2.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default color as the background of the window */
    wincl2.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */

        
    /* The class is registered, let's create the program*/
 hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           "Server",       /* Title Text */
           WS_CAPTION | WS_MINIMIZEBOX  //|WS_SIZEBOX  
        , /* default window */
          // CW_USEDEFAULT,       /* Windows decides the position */
           360,300,
           //CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    ShowWindow (hwnd, nFunsterStil);
    UpdateWindow(hwnd);
        if (!RegisterClassEx (&wincl2))
        return 0;
    while (GetMessage (&messages, NULL, 0, 0))
    {
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }
    return messages.wParam;
}
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  /* handle the messages */
    {
     case WM_CREATE:
......
           hEdit2 = CreateWindowEx(
WS_EX_CLIENTEDGE
                                    ,
                                   szClassName2,//"edit",
                                   edit2,    // <- das ist der Inhalt des Editfelds
                                   WS_CHILD | WS_VISIBLE //|// WS_VSCROLL |//ES_MULTILINE |
                                              //ES_AUTOVSCROLL,
                                              ,
                                   120, 50, 150, 25,
                                   hwnd,
                                   NULL,
                                   ((LPCREATESTRUCT) lParam) -> hInstance,
                                   NULL);

                   free(edit2);
                   SendMessage(hEdit2, WM_SETTEXT, 0, (LPARAM)port_str.c_str());
...
}
}

LRESULT CALLBACK Tab (HWND hEdit2, UINT message, WPARAM wParam, LPARAM lParam)
{
        switch(message)
        {
                 case WM_KEYDOWN:
             switch(wParam){
                        case VK_TAB:            SendMessage(hFortschritt, WM_SETTEXT, 0, (LPARAM)"-adwdwtt---"); break;
                        }   
            
            
                break; 
                  default:                     
             return DefWindowProc (hEdit2, message, wParam, lParam);             
                       }
                       
        }

leider gehts immernoch nicht..Wenn ich im editFenster Tab drücke passiert rein garnichts...
oder hab ich dich falsch verstanden/was falsch gemacht?
Danke für deine Mühen...
lg
kickerxy

ach und: wenn szClassName statt szClassName2 nehme steht in dem editFeld ein Textout mit "Willkommen", bzw es überlagert vermtl. das edit Feld und alle Buttons verlieren ihre Funktionalitäten
 
Zurück