Newsgroup: it.comp.programmare.win32
Titolo: ComboBox : non capisco

Non capisco perche' in un controllo "combo" i messaggi diretti al suo
controllo di edit non vanno alla Window Procedure del controllo .
Mi piacerebbe sapere proprio chi li gestisce .
Cambiando invece lo stile del controllo da DROPDOWN a DROPDOWNLIST
ecco che tutto funziona come ci si aspetta.
Ecco il codice :
#include <windows.h>
LRESULT CALLBACK WndProc      (HWND, UINT, WPARAM, LPARAM) ;
LRESULT CALLBACK ComboProc (HWND hwnd, UINT iMsg, WPARAM wParam,
LPARAM lParam) ;
LRESULT CALLBACK (*OldProc) (HWND hwnd, UINT iMsg, WPARAM wParam,
LPARAM lParam) ;
HINSTANCE HInstance ;
HWND hwndcombo  ;
 char Vector[][20] = { "Marte              ",
                       "Giove              ",
                       "Saturno            ",
                       "Urano              ",
                       "Nettuno            "
                      } ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
		            PSTR szCmdLine, int iCmdShow)
     {
     static char  szAppName[] = "Combo" ;
     MSG          msg ;
     HWND         hwnd ;
     WNDCLASSEX   wndclass ;
     wndclass.cbSize        = sizeof (wndclass) ;
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (hInstance, szAppName) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) COLOR_BACKGROUND+1 ;
     wndclass.lpszMenuName  = szAppName ;
     wndclass.lpszClassName = szAppName ;
     wndclass.hIconSm       = LoadIcon (hInstance, szAppName) ;
     RegisterClassEx (&wndclass) ;
     hwnd = CreateWindow (szAppName, "COMBO Box Demo Program",
                          WS_OVERLAPPEDWINDOW,
			                 CW_USEDEFAULT, CW_USEDEFAULT,
			                 CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     while (GetMessage (&msg, NULL, 0, 0))
          {
          if ( msg.hwnd == hwndcombo ) MessageBeep(0xFFFFFFFF);
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
          }
     return msg.wParam ;
     }
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM
lParam)
     {
     int index = 0 ;
     char buffer[30];
     switch (iMsg)
          {
          case WM_CREATE :
               HInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
               return 0 ;
/*Creazione del combo e subclassing */
          case WM_LBUTTONDOWN :
          hwndcombo = CreateWindow("combobox",NULL,
                      WS_CHILD | WS_VISIBLE | WS_VSCROLL |
CBS_DROPDOWN ,
                      10, 10, 200, 80,
                      hwnd, (HMENU)100, HInstance, NULL) ;
          SendMessage(hwndcombo,CB_ADDSTRING,0,LPARAM(Vector[0])) ;
          SendMessage(hwndcombo,CB_ADDSTRING,0,LPARAM(Vector[1])) ;
          SendMessage(hwndcombo,CB_ADDSTRING,0,LPARAM(Vector[2])) ;
          SendMessage(hwndcombo,CB_ADDSTRING,0,LPARAM(Vector[3])) ;
          SendMessage(hwndcombo,CB_ADDSTRING,0,LPARAM(Vector[4])) ;
          OldProc = (WNDPROC)
SetWindowLong(hwndcombo,GWL_WNDPROC,(LONG)ComboProc) ;
          SetFocus(hwndcombo) ;
          return 0 ;
          case WM_RBUTTONDOWN :
           GetWindowText(hwndcombo,buffer,19);
           MessageBox(hwnd,buffer,"System",MB_OK);
          return 0 ;
          case WM_DESTROY :
               PostQuitMessage (0) ;
               return 0 ;
          }
     return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
     }
 LRESULT CALLBACK ComboProc (HWND hwnd, UINT iMsg, WPARAM wParam,
LPARAM lParam)
{
     switch (iMsg) {
       case WM_KEYDOWN :
       if ( wParam == VK_TAB ) SetFocus(GetParent(hwnd)) ;
       break ;
     }
 
   return  CallWindowProc(OldProc,hwnd,iMsg,wParam,lParam) ;
}
Compilando ed eseguendo questo codice ,vedrete che la pressione del
tasto TAB non sposta il focus alla finestra principale.

tasto TAB non sposta il focus alla finestra principale.
In pratica nella ComboProc non arriva proprio il messaggio se lo stile
della combobox e' dropdown. Devi subclassare direttamente l'editbox.
Per ottenere la handle di tale editbox puoi usare:
POINT pt;
HWND hwndEdit1;
HWND hwndCombo1;
pt.x = 1; 
pt.y = 1; 
hwndEdit1 = ChildWindowFromPoint(hwndCombo1, pt); 
Ovviamente hwndEdit1 sara' la handle dell'editbox e hwndCombo1 e' la
handle della combobox. Vai a subclassare con:
lpfnEditWndProc = (WNDPROC) SetWindowLong(hwndEdit1, 
                GWL_WNDPROC, (DWORD) SubClassProc);
ed in SubClassProc avrai:
LRESULT CALLBACK SubClassProc(hwnd, msg, wParam, lParam) 
HWND hwnd; 
UINT msg; 
WPARAM wParam; 
LPARAM lParam; 
{ 
    switch (msg) { 
        case WM_KEYDOWN: 
            switch (wParam) { 
                case VK_TAB: 
                    // Codice per il tasto TAB
                    return 0; 
                case VK_ESCAPE: 
                    // Codice per il tasto Esc
                    return 0; 
                case VK_RETURN: 
                    // Codice per il tasto Invio 
                    return 0; 
            } 
            break; 
 
        case WM_KEYUP:
        case WM_CHAR: 
            switch (wParam) { 
                case VK_TAB: 
                case VK_ESCAPE: 
                case VK_RETURN: 
                    return 0; 
            } 
    } 
 
    return CallWindowProc(lpfnEditWndProc, hwnd, 
        msg, wParam, lParam); 
}
Bye.

una dialogbox.
TI RINGRAZIO .
Provo il codice e poi magari  se ho ancora qualche dubbio ne
ripaliamo...... se vuoi .
Ciao

ecco che tutto funziona come ci si aspetta.
Ti consiglio si usare Spy++ (e' un tool distribuito assieme al MS VC++) per
vedere quali messaggi vengono inviati ai vari controlli.
Un OutputDebugString("Eccomi!") eseguito in risposta al WM_KEYDOWN del
controllo ha qualche effetto?
Saluti,
    Mardy

ed in SubClassProc avrai:
Ho modificato il codice come mi hai suggerito ma non ha sortito alcun
effetto.
Funziona sul tuo Pc ?
L'handle che mi restituisce la funzione ChildWindowFromPoint e' sempre
quella del ComboBox e non quella del controllo di Edit.
ciao

Saluti,
Ti ringrazio per i consigli .
Ciao

effetto.
Prova a centrare la coordinata orizzontale (usando GetClientRect sulla
combobox e mettendo pt.x = rect.right / 2, con rect passato alla
suddetta funzione). Oppure poni pt.x = 5 e pt.y = 5 giusto per fare
andare il punto centralmente piu' vicino alla editbox.
Inoltre puoi anche gestire il messaggio WM_CTLCOLOREDIT nella window
procedure della combobox, il quale messaggio ti passa la handle della
editbox (dopo di che potrai, per una sola volta pero', modificare la
window procedure dell'editbox).
Bye.

quella del ComboBox e non quella del controllo di Edit.
Forse la tua combobox ha dei margini personalizzati? Prova con:
hwndEdit1 = GetWindow(hwndCombo1, GW_CHILD);
Saluti,
    Mardy

hwndEdit1 = GetWindow(hwndCombo1, GW_CHILD);
Brava, funziona.
A questo punto e' necessaria una spiegazione su come sono strutturate
queste cavolo di COMBOBOX ..... sempre prescindendo dalla tua
disponibilita' .
Ciao
 

disponibilita' .
Non c'e' molto da dire: il campo in cui digiti il testo e' una normale
EditBox, che pero' non ti e' accessibile direttamente, in quanto "figlia"
della combobox. L'istruzione che ti ho scritto sopra serve appunto per
ottenere l'handle della EditBox a partire d quello della ComboBox.
Saluti,
    Mardy

ottenere l'handle della EditBox a partire d quello della ComboBox.
Ti ringrazio per  le info . Ciao .