Newsgroup: it.comp.programmare.win32
Titolo: [VC++] Implementare WM_KEYDOWN

Ho notato che nella gestione delle procedure del dialogo la notifica
WM_KEYDOWN non arriva ! Pero tra i message loop si ! Come faccio per
implementare il WM_KEYDOWN ? Devo creare una funzione io ?


I messaggi WM_KEYDOWN/WM_KEYUP vengono inviati alla finestra che ha il 
focus e per finestra intendo anche un controllo. Se la tua dialog-box ha 
un controllo 'edit' che ha il focus, solo quel controllo ricevera' 
questi due messaggi e non certo la dialog-box.
Non so ovviamente cosa devi fare di preciso ma se stai usando una dialog 
box non modale (parli del message loop, quindi lo suppongo), puoi usare 
gli acceleratori di tastiera.

 ha scritto nel messaggio
news:c77l12$a3p$1...@newsreader.mailgate.org...

Cosa sono gli acceleratori ? E cmq io ho una combobox che alla pressione del
tasto invio mi deve eseguire una funzione !

 tasto invio mi deve eseguire una funzione !
Allora per il momento ignora gli acceleratori di tastiera.
In una dialog box quando premi 'invio' viene mandato alla dialog-box un 
messaggio WM_COMMAND con l'identificativo IDOK (costante predefinita) se 
non c'e' un pulsante di default oppure l'identificativo del pulsante di 
default, se esiste.
Se ti basta questo, puoi gestire questo evento.
Tipicamente in una dialog-box un 'invio' indica un '...ho finito...' e 
si chiude la dialog con un EndDialog, ma tu puoi fare ovviamente quello 
che vuoi.

 ha scritto nel messaggio
news:c77plv$grr$1...@newsreader.mailgate.org...

ok è l'idok dove lo recupero ?

 ok è l'idok dove lo recupero ?
Allora: IDOK e' una costante predefinita e vale 1 (vedere in winuser.h).
Tu devi rispondere a WM_COMMAND quando ti arriva questo IDOK. Come ti ho 
gia' detto questo vale se non hai un pulsante di default, altrimenti se 
lo avessi riceveresti al posto di IDOK, l'id del pulsante.

 > ok č l'idok dove lo recupero ?

Ho provato quello che dici ma in qualunque controllo premi invio mi va a
IDOK !! Io ne ho bisogno solo nella combo !

 IDOK !! Io ne ho bisogno solo nella combo !
Ah beh, allora e' un'altra storia ...
Il fatto che 'invio'--->BN_CLICKED con IDOK o <id controllo> e' una cosa 
generica in una dialog-box.
Se ti serve solo nella combo, uhm ... dovrei pensarci !

 ha scritto nel messaggio
news:c77sh1$l3s$1...@newsreader.mailgate.org...

Non si potrebbe usare la procedura PreTransleteMessage ?

 Non si potrebbe usare la procedura PreTransleteMessage ?
Non la conosco ma mi sembra che sia qualcosa legato alla programmazione 
con le MFC e non per il Win32.
Adesso vado a pranzo ... ci penso !

 ha scritto nel messaggio
news:c77tr1$n8k$1...@newsreader.mailgate.org...

Ok TNX ! Un'altra domanda , ma creare una finestra con CreateDialog() e
invee con CreateWindow(), porta dei cambiamenti ?



Sono due cose diverse, basta che dai un occhio alla guida/msdn cercando le
due api che hai citato.
Stefano "HappyMan" (Lake Maggiore - Italy)
-- 
The Personal Framework for Object Oriented Windows Development (Win32)
http://www.sgr.info
Email happyman69 (at) 
despammed.com

 ha scritto nel messaggio
news:qqb1kbj5pryr.10mbsq9z5gjmg$.dlg@40tude.net...

Si okey ma un programma posso crearlo partendo da un CreateDialog ?

 Si okey ma un programma posso crearlo partendo da un CreateDialog ?
Certamente !! Purche' ti ricordi 3 cose:
1) Devi gestire tu il loop dei messaggi (con CreateDialog la dialog non 
e' modale).
2) Nel loop dei messaggi devi usare la 'famosa' IsDialogMessage().
3) La window-procedure (o meglio direi dialog-procedure) e' come quella 
che useresti con la DialogBox() e non come quella che si usa quando 
registri la classe e poi usi CreateWindow().
Ma li hai visti gli esempi sul mio sito ? :P

 ha scritto nel messaggio
news:c781b1$s7e$1...@newsreader.mailgate.org...

Certo che li ho visti :) !!! Pero quello che volevo dire , è formalmente
sbagliato creare un programma con un CreateDialog !
La differenza da quello che ho capito sta solo nel fatto che il CreateDialog
prende un dialogo dalle risorse mentre il createwindow la crea exnuova
,giusto ?

 ,giusto ?
Giusto ! La CreateWindow crea la sola finestra e basta. Qualunque 
controllo che ci vuoi mettere dentro (static, edit, combo, ecc...) lo 
devi creare tu con ulteriori CreateWindow ... e se hai tanti controlli 
??? Giustamente diresti ... che palle !
A quel punto usi le dialog-box (modali con DialogBox() o non modali con 
CreateDialog()) e risolvi il problema.
Per come la vedo io, CreateWindow e' l'ideale per creare applicazioni 
nello stile di explorer, blocco note o paint. Dove hai una finestra che 
ridimensioni a piacere e con pochi controlli o ancora in cui ci devi 
disegnare tu dentro completamente.
Le dialog-box servono invece per "dialogare" con l'utente, quindi ci 
metti tutti i controlli che vuoi (in modo "visuale", permettimi 
l'espressione, con il resource editor) e in cui magari hai i soliti 
tasti OK/Annulla.

 ha scritto nel messaggio
news:c783os$vl7$1...@newsreader.mailgate.org...

Pero ho notato che il WM_KEYDOWN , creando la dialog con la CreateWindow
funziona ,mentre con il CreateDialog no ! Come mai ?

 funziona ,mentre con il CreateDialog no ! Come mai ?
Con CreateWindow non crei una dialog !
Se ti riferisci al tasto di 'invio' di cui abbiamo appena discusso 
prima, il "responsabile" e' la IsDialogMessage(). Nelle dialog box 
esiste una gestione particolare di svariati tasti e combinazioni di 
tasti. TAB, Shift+TAB, ESC, INVIO, ecc... li trovi ben spiegati in MSDN 
nella sezione dedicata alle dialog-box.

 ha scritto nel messaggio
news:c784tb$1md$1...@newsreader.mailgate.org...

Non ho capito bene ancora , per esempio, un'applicazione come outlook, si
dovrebbe usare come finestra principale un CreateDialog oppure una
CreateWindow ?

 CreateWindow ?
A parte il fatto che ovviamente non so come sia stato sviluppato un 
software come Outlook, sarei portato a pensare che la sua finestra 
principale (quella top-level) e' stata creata come "finestra" e non 
certo come "dialog-box". Poi che abbiano usato CreateWindow, 
CreateWindowEx o le equivalenti in un framework come MFC, non ne ho la 
piu' pallida idea !

 ha scritto nel messaggio
news:c78c2g$c5b$1...@newsreader.mailgate.org...

Ohhh è questo che volevo sapere ! Quindi la finestra principale dovrebbe
essere una window non una dialog !

 essere una window non una dialog !
Ahhhh ! Dipende !!! Certamente la maggior parte delle applicazioni hanno la
finestra principale creata come "finestra" e non come "dialog-box". Prendi
invece ad esempio l'utility "Mappa caratteri" di Windows. Questa usa una
dialog box. Sbirciando con il tool Spy++ ho infatti visto che usa come
classe "MyDlgClass", cioe' si crea una dialog-box custom con la sua classe
specifica.

 ha scritto nel messaggio
news:PYRlc.194379$rM4.8...@news4.tin.it...

Una cosa , mi potresti fare un esempio di come creare un controllo static su
di una finestra , io ho provato a mettere :
 CreateWindow("static", "prova",
                           WS_CHILD | WS_VISIBLE | WS_BORDER|SS_LEFT,
                           10, 10, 200, 80,hWnd, NULL,
                           g_hInstance, NULL);
dentro WM_INITDIALOG ma non me la crea ! :(

 dentro WM_INITDIALOG ma non me la crea ! :(
Ho preso il tuo codice qui sopra e l'ho messo in risposta a 
WM_INITDIALOG utilizzando il mio esempio di codice per dialog-box non 
modale (ho solo messo hDlg invece di hWnd, vedi al punto 3), e ti 
assicuro che il controllo static lo crea e si vede !!!
Ti posso dire alcune cose al riguardo:
1) Non e' che per caso hai creato la tua finestra principale con 
CreateWindow ??? Perche' cosi' ovvio che non ti funziona. WM_INITDIALOG 
e' un messaggio un po' particolare. Intanto vale *solo* per le 
dialog-box, cioe' utilizzando DialogBox<XXX> oppure CreateDialog<XXX>. 
Inoltre viene inviato immediatamente e direttamente alla dialog 
procedure senza passare da alcun loop dei messaggi.
Es.:
hDlg = CreateDialog (....
^^^^ Il messaggio WM_INITDIALOG e' gia' stato "dispacciato" alla dialog 
procedure prima ancora di entrare nel message loop !!!
while (GetMessage (&msg, ....
{
    ....
}
2) Quando crei altri controlli con una CreateWindow, il 9° parametro, 
quello che sarebbe hMenu, e' invece l'identificativo del controllo, 
quindi si dovrebbe usare un qualcosa come:
#define IDS_STATIC1   1000
e nella CreateWindow ... (HMENU) IDS_STATIC1
3) Io per evitare confusioni uso "hWnd" per identificare finestre 
"normali" e "hDlg" per identificare dialog-box (anche se poi tutte e due 
sono di tipo HWND).
Ciao

 ha scritto nel messaggio
news:c7a8j8$i2d$1...@newsreader.mailgate.org...

Si avevo sbagliato, avevo creato la finestra con CreateWindow e quindi
initdialog non poteva esistere essendo una window ! Ora l'ho capito !
Pero non ho capito una cosa !
se creo il controllo edit e button con
 iStatic =
CreateWindow("edit","Test",WS_CHILD|WS_VISIBLE|WS_BORDER,10,10,100,25,hWnd,N
ULL,NULL,NULL);
apparte il font dei caratteri è diverso, ma lo stile window xp mi appare
solo sul button e non sull'edit, come mai ? Ho tralasciato qualceh style ?

 ha scritto nel messaggio
news:c77tr1$n8k$1...@newsreader.mailgate.org...

Senti andrea avrei pensato una cosa ! Ho creato un window tramite create
window
e ho pensato , se metto una cosa del genre nei message loop puo essere una
cosa fattibile, cioč č formalmente corrette o ci sono altri modi per farlo
piu standard diciamo !
    //-- Messages loop --
    while (GetMessage (&msg, NULL, 0, 0))
    {
        if (msg.hwnd==hWndEdit1 &&
msg.message==WM_KEYDOWN)MessageBox(0,"Tasto premuto",0,0);
        TranslateMessage (&msg);
        DispatchMessage (&msg);
    }

     }
Alterare il loop dei messaggi non penso sia certo proibito ! D'altronde 
se ci sono funzioni come la IsDialogMessage ... vuol dire che a volte e' 
necessario elaborare in un certo modo particolare/complesso i messaggi.
Ovviamente bisogna farlo in modo un po' pulito. Intanto nel loop dei 
messaggi si dovrebbe operare solo ed esclusivamente sui messaggi e 
basta. Mettere una MessageBox o fare qualche altra cosa, secondo me, e' 
sconsigliabile.
Una soluzione puo' essere questa:
BOOL IsChildReturn (HWND hWnd, LPMSG lpmsg, int nctl, int *vidctl)
{
     BOOL bRet=FALSE;
     HWND hWndParent;
     int  id, i;
     if ((lpmsg->message == WM_KEYDOWN || lpmsg->message == WM_KEYUP) &&
         lpmsg->wParam == VK_RETURN)
     {
         hWndParent = GetParent (lpmsg->hwnd);
         if (hWndParent == hWnd)
         {
             id = GetDlgCtrlID (lpmsg->hwnd);
             for (i=0; i<nctl; i++)
             {
                 if (vidctl[i] == id)
                 {
                     if (lpmsg->message == WM_KEYDOWN)
                     {
                         NMHDR nmhdr;
                         nmhdr.hwndFrom = lpmsg->hwnd;
                         nmhdr.idFrom = id;
                         nmhdr.code = NM_RETURN;
                         SendMessage (hWndParent, WM_NOTIFY, id, 
(LPARAM) &nmhdr);
                     }
                     bRet = TRUE;
                     break;
                 }
             }
         }
     }
     return bRet;
}
....
....
Nella WinMain
    int vidctl[1] = { IDC_EDIT1 };   // Ne metti quanti ne vuoi
    ....
    while (GetMessage (&msg, NULL, 0, 0))
    {
       if (!IsChildReturn (hDlg, &msg, 1, vidctl) &&
           !IsDialogMessage (hDlg, &msg))
       {
          TranslateMessage (&msg);
          DispatchMessage (&msg);
       }
    }
Ogni volta che premi 'invio' su uno dei controlli child il cui <id> e' 
elencato nell'array vidctl, la IsChildReturn lo riconosce, non passa il 
messaggio oltre alla Translate/Dispatch ma invia alla finestra padre del 
controllo (quella principale) un messaggio WM_NOTIFY nella forma 
standard con code=NM_RETURN.
A quel punto, ricevuto il notify, fai tu quello vuoi !!!
La IsChildReturn me lo sono inventata io ... ma ho usato 
WM_NOTIFY/NM_RETURN perche' ho visto che sono gia' definiti (non so bene 
come e dove vengano usati ... io non li ho mai usati).
Prova ...

 ha scritto nel messaggio
news:c7aq13$c9h$1...@newsreader.mailgate.org...

Ok , quindi per usare la funzione WM_KEYDOWN bisogna per forza fare cosi
,cioč gestire i messaggi e reindirizzarli verso funzioni ?

 ha scritto nel messaggio
news:c7aq13$c9h$1...@newsreader.mailgate.org...

Che ne dici di una procedura del genere
bool PreProcessMsg(MSG msg)
{
 switch (msg.message){
  case WM_KEYDOWN :
   switch(msg.wParam){
    case VK_RETURN:
     if (msg.hwnd==hWndEdit1)MessageBox(0,"Premuto Invio","Messaggio",0);
     return TRUE;
    break;
   }
  break;
 }
 return FALSE;
}
poi nel message loop cosi
    //-- Messages loop --
    while (GetMessage (&msg, NULL, 0, 0))
    {
        if (!PreProcessMsg(msg))
       {
         TranslateMessage (&msg);
         DispatchMessage (&msg);
       }
    }

[cut]
Ufffh ! Si, certo che cosi' tecnicamente funziona pure ! (hWndEdit1 deve 
essere pero' globale e il messaggio ti conviene passarlo per indirizzo 
non per valore)
Il codice che ho fatto io comunque e' piu' generico, opera solo su 
messaggi e mi permette di filtrare solo i controlli che voglio e senza 
dover specificare i loro handle.
Anche se non mi sembra una buona cosa mettere una MessageBox nel loop ma 
se a te basta cosi' ... a me va benissimo !!

 ha scritto nel messaggio
news:c7b1tq$o81$2...@newsreader.mailgate.org...

Apparte il messagebox che non è che rimanga li , lo uso solo per vedere se
funziona solo per prova poi lo levo , ma poi in questo modo riesco  a
controllare meglio tutti i tipi di messaggi mentre tu quando avviene
l'evento keydown lo rimandi ad un notify della window se non sbaglio !