Win API - Správy a LISTBOX
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu
Reklama
Reklama

Win API - Správy a LISTBOXWin API - Správy a LISTBOX

 

Win API - Správy a LISTBOX

Google       Google       23. 5. 2009       13 225×

V tomto dieli sa budeme venovať vzájomnej komunikácii medzi oknami a na záver si ukážeme vytvorenie ovládacieho prvku LISTBOX. Pôvodne mal byť tento článok o niečom inom (FTP), ale presunieme si to do ďalšieho dielu.

Reklama
Reklama

Komunikácia medzi oknami

Prebieha pomocou správ. Je to veľmi jednoduché, pretože to funguje presne tak ako doteraz, keď Windows zasielal správy našim oknám. Okná si môžu správy zasielať aj medzi sebou a to pomocou funkcie:

 SendMessage( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
Jednotlivé parametre sú:
  • hWnd - manipulátor okna, ktorému chceme správu zaslať,
  • Msg - identifikátor správy, ktorú chceme zaslať,
  • hWnd - wParam správy,
  • hWnd - lParam správy.
Správy odoslané pomocou tejto funkcie sa dostanú až k procedúre okna, kde ich môžeme spracovať rovnako ako napr. správu WM_CREATE, WM_PAINT a podobne.

Čo sú správy

Správy sú obyčajné čísla, ktoré majú pomocou príkazu #define priradený identifikátor. Napríklad správa WM_CREATE má hodnotu 1, WM_PAINT = 15, a podobne. Pre zaujímavosť uvádzam úryvok zo súboru winuser.h, kde sú tieto správy definované.

#define WM_CREATE 1
#define WM_CTLCOLORBTN 309
#define WM_CTLCOLORDLG 310
#define WM_CTLCOLOREDIT 307
#define WM_CTLCOLORLISTBOX 308
#define WM_CTLCOLORMSGBOX 306
#define WM_CTLCOLORSCROLLBAR 311
#define WM_CTLCOLORSTATIC 312
#define WM_CUT 768
#define WM_DEADCHAR 259
#define WM_DELETEITEM 45
#define WM_DESTROY 2
#define WM_DESTROYCLIPBOARD 775
#define WM_DEVICECHANGE 537
#define WM_DEVMODECHANGE 27
#define WM_DISPLAYCHANGE 126
#define WM_DRAWCLIPBOARD 776
#define WM_DRAWITEM 43
#define WM_DROPFILES 563
#define WM_ENABLE 10
#define WM_ENDSESSION 22
#define WM_ENTERIDLE 289
#define WM_ENTERMENULOOP 529
#define WM_ENTERSIZEMOVE 561
#define WM_ERASEBKGND 20
#define WM_EXITMENULOOP 530
#define WM_EXITSIZEMOVE 562
#define WM_FONTCHANGE 29
#define WM_GETDLGCODE 135
#define WM_GETFONT 49
#define WM_GETHOTKEY 51
#define WM_GETICON 127
#define WM_GETMINMAXINFO 36
#define WM_GETTEXT 13
#define WM_GETTEXTLENGTH 14
/* FIXME/CHECK: Are WM_HANDHEL{FIRST,LAST} valid for WINVER < 0x400? */
#define WM_HANDHELDFIRST 856
#define WM_HANDHELDLAST 863
#define WM_HELP 83
#define WM_HOTKEY 786
#define WM_HSCROLL 276
#define WM_HSCROLLCLIPBOARD 782
#define WM_ICONERASEBKGND 39
#define WM_INITDIALOG 272
#define WM_INITMENU 278
#define WM_INITMENUPOPUP 279
#define WM_INPUTLANGCHANGE 81
#define WM_INPUTLANGCHANGEREQUEST 80
#define WM_KEYDOWN 256
#define WM_KEYUP 257
#define WM_KILLFOCUS 8
#define WM_MDIACTIVATE 546
Ak by mal niekto záujem, nie je problém nájsť si súbor winuser.h, otvoriť ho a trochu si ho poobzerať. Práve vďaka tomuto systému, kde správa ako text predstavuje určité číslo, ide o systém, ktorý je pomerne jednoduchý na zapamätanie (ťažko by ste si pamätali, že pri vytvorení okna dostane okno "správu" 1, pri maľovaní 15, pri pustení tlačidla na klávesnici zasa 257 a pod.). Okrem týchto preddefinovaných správ môžeme pomocou funkcie SendMessage(...) posielať aj naše "vymyslené" správy. Ak chceme nášmu dcérskemu oknu povedať, že má napr. prepísať text v nadpise, pošleme mu SendMessage(hWndChild,MM_PREPIS,NULL,NULL); pričom identifikátoru MM_PREPIS priradíme hodnotu, ktorá by sa nemala zhodovať s preddefinovanými správami. Túto správu potom jednoducho spracujeme pomocou procedúry dcérskeho okna:
LRESULT CALLBACK WndProc(HWND hWndChild, UINT message, WPARAM wParam, LPARAM lParam)   
{   
        switch(message)   
        {  case MM_PREPIS:
           /*Kód ktorý chcete vykonať*/
           break;
          .........................
          case WM_DESTROY:   
          PostQuitMessage(0);   
          return 0;   
        }   
        return DefWindowProc(hWnd, message, wParam, lParam);   
}  
Pomocou správ taktiež komunikujeme s ovládacími prvkami. Teraz si to ukážeme na jednoduchom príklade s využitím ovládacieho prvku typu LISTBOX.

LISTBOX

Na úvod uvediem kód ukážkového programu. Pre zmenu je použitý a upravený kód z Dev C++.

#include 
#define Pridaj              101
#define Odober              102
#define Zobraz              103
#define EditText            104
#define EditData            105

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
char szClassName[ ] = "WindowsApp";
HWND button[3],edit,listBox;
char buffer[256];
                                 

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;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           "Windows App",       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           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 */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nFunsterStil);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}


/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  /* handle the messages */
    {   case WM_CREATE:
        edit = CreateWindow("EDIT","Text", WS_CHILD | WS_VISIBLE | ES_CENTER | ES_AUTOHSCROLL , 10,20,100,20,hwnd,(HMENU)EditText,NULL,NULL);
        button [0] = CreateWindow("BUTTON","Pridaj", WS_CHILD | WS_VISIBLE, 120,20,100,20,hwnd,(HMENU)Pridaj,NULL,NULL);
        button [1] = CreateWindow("BUTTON","Odober", WS_CHILD | WS_VISIBLE, 10,50,100,20,hwnd,(HMENU)Odober,NULL,NULL);
        button [2] = CreateWindow("BUTTON","Zobraz", WS_CHILD | WS_VISIBLE, 120,50,100,20,hwnd,(HMENU)Zobraz,NULL,NULL);        
        listBox = CreateWindow("LISTBOX","", WS_CHILD | WS_VISIBLE | WS_BORDER | LBS_HASSTRINGS , 230,20,150,100,hwnd,NULL,NULL,NULL); 
        break;
        case WM_COMMAND:
             switch(LOWORD(wParam))
             {case Pridaj:
                   GetWindowText(edit,buffer,255);
                   index = SendMessage(listBox,LB_INSERTSTRING,-1,(LPARAM)&buffer);
                   break;
             case Odober:
                  index = SendMessage(listBox,LB_GETCURSEL,NULL,NULL);
                  SendMessage(listBox,LB_DELETESTRING ,(WPARAM)index,NULL);                  
                  break;
             case Zobraz:
                  index = SendMessage(listBox,LB_GETCURSEL,NULL,NULL); 
                  SendMessage(listBox,LB_GETTEXT,(WPARAM)index,(LPARAM)&buffer); 
                  MessageBox(hwnd,buffer,"Text:",MB_OK);
                  break;
             default:
                   break;
                                   }
             break;
        case WM_DESTROY:
            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}
Teraz si vysvetlíme základné časti programu. Nebudeme ho však vysvetľovať celý. Ak budete potrebovať vysvetliť program podrobnejšie, pozrite do úvodnych dielov tohoto seriálu (od Kamila Skálu (Stormu)), alebo článok Direct 3D - 1. diel (odo mňa).
#define Pridaj              101
#define Odober              102
#define Zobraz              103
#define EditText            104
#define EditData            105

char szClassName[ ] = "WindowsApp";
HWND button[3],edit,listBox;
char buffer[256];
Ide o identifikátory ovládacich prvkov a o potrebné premenné. Ďalej sa pozrieme na spracovanie jednotlivých správ, zvyšku by ste mali rozumieť...
case WM_CREATE:
        edit = CreateWindow("EDIT","Text", WS_CHILD | WS_VISIBLE | ES_CENTER | ES_AUTOHSCROLL , 10,20,100,20,hwnd,(HMENU)EditText,NULL,NULL);
        button [0] = CreateWindow("BUTTON","Pridaj", WS_CHILD | WS_VISIBLE, 120,20,100,20,hwnd,(HMENU)Pridaj,NULL,NULL);
        button [1] = CreateWindow("BUTTON","Odober", WS_CHILD | WS_VISIBLE, 10,50,100,20,hwnd,(HMENU)Odober,NULL,NULL);
        button [2] = CreateWindow("BUTTON","Zobraz", WS_CHILD | WS_VISIBLE, 120,50,100,20,hwnd,(HMENU)Zobraz,NULL,NULL);        
        listBox = CreateWindow("LISTBOX","", WS_CHILD | WS_VISIBLE | WS_BORDER | LBS_HASSTRINGS , 230,20,150,100,hwnd,NULL,NULL,NULL); 
Vytvorenie okna EDIT a BUTTON by vám už malo byť známe a LISTBOX pochopíte v tomto článku. LISTBOX vytvárate rovnako ako BUTTON a EDIT s tým rozdielom, že ako triedu použijete "LISTBOX". Na komunikáciu s LISTBOX-om budeme používať správy a funkciu SendMessage(...). Ako? To uvidíte neskôr.
case WM_COMMAND:
             switch(LOWORD(wParam))
             {case Pridaj:
                   GetWindowText(edit,buffer,255);
                   index = SendMessage(listBox,LB_INSERTSTRING,-1,(LPARAM)&buffer);
                   break;
Najprv získame text z EDITBOX-u pomocou GetWindowText(..) a potom ho pridáme do zoznamu SendMessage(..).
  • listBox je manipulátor LISTBOX-um ktorému posielame správu,
  • LB_INSERTSTRING je identifikátor správy, ktorú posielame oknu (LB_INSERTSTRING - vloží reťazec do zoznamu),
  • lParam a wParam pre každú správu znamená niečo iné. Pre túto správu -1 znamená, že pridá reťazec na koniec zoznamu a &buffer je adresa bufferu v ktorom je text.
case Odober:
                  index = SendMessage(listBox,LB_GETCURSEL,NULL,NULL);
                  SendMessage(listBox,LB_DELETESTRING ,(WPARAM)index,NULL);                  
                  break;
             case Zobraz:
                  index = SendMessage(listBox,LB_GETCURSEL,NULL,NULL); 
                  SendMessage(listBox,LB_GETTEXT,(WPARAM)index,(LPARAM)&buffer); 
                  MessageBox(hwnd,buffer,"Text:",MB_OK);
                  break;
Najprv zistíme pomocou zaslania správy LB_GETCURSEL, ktorá položka v LISTBOX-e je vybraná. Potom ju zmažeme pomocou LB_DELETESTRING. Na zobrazenie položky zistíme najprv jej index v LISTBOX-e (LB_GETCURSEL) a potom získame text na danej polohe pomocou LB_GETTEXT, pričom wParam je práve index reťazca v LISTBOX-e a lParam je adresa bufferu na uloženie daného reťazca. Pre podrobnejšie informácie viď MSDN.com.

Čo dalej? Verím, že ste plní očakávania a preto do ďalšieho dielu zaradím niečo o FTP, niečo o súboroch, niečo o tlači a tak podobne. Ako bonus napíšem aj o programovaní pre Windows Mobile.

×Odeslání článku na tvůj Kindle

Zadej svůj Kindle e-mail a my ti pošleme článek na tvůj Kindle.
Musíš mít povolený příjem obsahu do svého Kindle z naší e-mailové adresy kindle@programujte.com.

E-mailová adresa (např. novak@kindle.com):

TIP: Pokud chceš dostávat naše články každé ráno do svého Kindle, koukni do sekce Články do Kindle.

3 názory  —  3 nové  
Hlasování bylo ukončeno    
0 hlasů
Google
Autor sa venuje programovaniu v C++, PHP a JavaScript-e. Taktiež programujte grafiku pomocou Direct 3D a OpenGL. Mimo IT má rád dobré filmy, cyklistiku, lyžovanie a plávanie.
Web    

Nové články

Obrázek ke článku NEWTON Media prohledá 200  milionů mediálních zpráv během sekund díky Cisco UCS

NEWTON Media prohledá 200 milionů mediálních zpráv během sekund díky Cisco UCS

Česká společnost NEWTON Media provozuje největší archiv mediálních zpráv ve střední a východní Evropě. Mezi její zákazníky patří například ministerstva, evropské instituce nebo komerční firmy z nejrůznějších oborů. NEWTON Media rozesílá svým zákazníkům každý den monitoring médií podle nastavených klíčových slov a nabízí online službu, kde lze vyhledat mediální výstupy v plném znění od roku 1996.

Reklama
Reklama
Obrázek ke článku Delphi 10.1.2 (Berlin Update 2) – na co se můžeme těšit

Delphi 10.1.2 (Berlin Update 2) – na co se můžeme těšit

Touto roční dobou, kdy je zem pokrytá barevným listím a prsty křehnou v mrazivých ránech, se obvykle těšíme na zbrusu novou verzi RAD Studia. Letos si však ale budeme muset počkat na Godzillu a Linux až do jara. Vezměme tedy za vděk alespoň updatem 2 a jelikož dle vyjádření pánů z Embarcadero se budou nové věci objevovat průběžně, pojďme se na to tedy podívat.

Obrázek ke článku Konference: Moderní datová centra pro byznys dneška se koná už 24. 11.

Konference: Moderní datová centra pro byznys dneška se koná už 24. 11.

Stále rostoucí zájem o cloudové služby i maximální důraz na pružnost, spolehlivost a bezpečnost IT vedou k výrazným inovacím v datových centrech. V infrastruktuře datových center hraje stále významnější roli software a stále častěji se lze setkat s hybridními přístupy k jejich budování i provozu.

Obrázek ke článku Konference: Mobilní technologie mají velký potenciál pro byznys

Konference: Mobilní technologie mají velký potenciál pro byznys

Firmy by se podle analytiků společnosti Gartner měly  rychle přizpůsobit skutečnosti, že mobilní technologie už zdaleka nejsou horkou novinkou, ale standardní součástí byznysu. I přesto - nebo možná právě proto - tu nabízejí velký potenciál. Kde tedy jsou ty největší příležitosti? I tomu se bude věnovat již čtvrtý ročník úspěšné konference Mobilní řešení pro business.

loadingtransparent (function() { var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true; po.src = 'https://apis.google.com/js/plusone.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s); })();
Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032016 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý