Po zapoznaniu się z przyciskami nadszedł czas na kolejną kontrolkę, kontrolkę "Edit", czyli tzw. pole edycyjne, gdzie możemy wpisać jakiś tekst.

Inicjacja kontrolek w programie.

Standardowo musimy dołączyć odpowiedni plik nagłówkowy o nazwie "commctrl.h", a w opcjach projektu dołączamy bibliotekę libcomclt32.a

Tworzenie kontrolki

Tutaj nie ma wiele nowego, każdą kontrolkę tworzymy funkcją CreateWindowEx:

#include <windows.h>
#include <commctrl.h>

HWND hEdit,hWnd;
CHAR szClassName[]=
"OknoRodzica"
;
HINSTANCE* hInst;

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

INT WINAPI WinMain(HINSTANCE hInstance,HINSTANCE,LPSTR lStart,INT nShow)
{
  hInst=&hInstance;
  WNDCLASSEX wc;
  wc.hInstance=*hInst;
  wc.lpszClassName=szClassName;
  wc.lpfnWndProc=WndProc;
  wc.style=
0
;
  wc.cbSize=sizeof(WNDCLASSEX);
  wc.hIcon=LoadIcon(
0
,IDI_APPLICATION);
  wc.hIconSm=LoadIcon(
0
,IDI_APPLICATION);
  wc.hCursor=LoadCursor(
0
,IDC_ARROW);
  wc.lpszMenuName=
0
;
  wc.cbClsExtra=
0
;
  wc.cbWndExtra=
0
;
  wc.hbrBackground=(HBRUSH)COLOR_BACKGROUND;
  if(!RegisterClassEx(&wc)) return
0
;
  hWnd=CreateWindowEx(
0
,szClassName,
"Tworzenie edit'a"
,WS_OVERLAPPEDWINDOW,
20
,
20
,
600
,
300
,
0
,
0
,*hInst,
0
);
  ShowWindow(hWnd,nShow);
  MSG msgs;
  while(GetMessage(&msgs,
0
,
0
,
0
))
  {
    TranslateMessage(&msgs);
    DispatchMessage(&msgs);
  }
  return msgs.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wPar,LPARAM lPar)
{
  switch(msg)
  {
    case WM_CREATE:
      
//funkcja tworząca kontrolkę

      hEdit=CreateWindowEx(
0
,WC_EDIT,
"Tekst w polu edycji"
,WS_CHILD|WS_VISIBLE,
20
,
20
,
200
,
20
,hwnd,
0
,*hInst,
0
);
      break;
    case WM_DESTROY:
      DestroyWindow(hEdit);
      PostQuitMessage(
0
);
      break;
    default:
      return DefWindowProc(hwnd,msg,wPar,lPar);
  }
  return
0
;
}

Powinniśmy mniej więcej uzyskać taki efekt:

Każdy chyba widzi, że "goła" kontrolka edit, lekko mówiąc jest brzydka. Warto nadać jej jakieś estetyczne style, takie jakie nadawalimy w oknach, ja bym proponawał dać jej WS_EX_CLIENTEDGE, aby ją zagłębić, powinna nabrać jakiegoś wyglądu.

...
hEdit=CreateWindowEx(WS_EX_CLIENTEDGE,WC_EDIT,
"Tekst w polu"
,WS_CHILD|WS_VISIBLE,
20
,
20
,
200
,
20
,hwnd,
0
,*hInst,
0
);
...

Zagłębiona wygląda o niebo lepiej, można oczywiście jeszcze poeksperymentować, ale to już zostawiam wam.

Obsługa tekstu w kontrolce

Dobrze, mając już gotową kontrolkę, użytkownik może wpisywać do niej tekst. Tylko jak możemy sprawdzić co użytkownik sobie napisał? Otóż możemy posłużyć się funkcją GetWindowText(). Funkcja ta pobiera tekst z kontrolki(lub każdego okna) do łańcucha znaków.

INT GetWindowText(HWND hwnd,LPSTR lpStr,INT size);

HWND hwnd
Pierwszy parametr to uchwyt do kontrolki, z której pobieamy tekst.

LPSTR lpStr
Drugi parametr to wskaźnik do łańcucha znaków, do którego zostanie zapisany tekst z kontrolki.

INT size
Określa ile znaków ma zostać przepisane do łańcucha znaków.

Jeżeli funkcja się nie powiedzie, zwraca 0, natomiast jeżeli wszystko pójdzie ok, zwraca długość odczytanego tekstu.

Potrafimy już pobrać tekst z kontrolki, ale to nie koniec, czasem trzeba kilkukrotnie zmienić tekst w kontrolce, do ustawienia jakiegoś tekstu w kontrolce słuzy funkcja SetWindowText().

BOOL SetWindowText(HWND hwnd,LPCSTR lpStr);

HWND hwnd
Uchwyt kontrolki do której ma zostać zapisany tekst.

LPCSTR lpStr
Wskaźnik do łańcucha znaków, który zostanie zapisany w kontrolce.

Jeżeli funkcja się nie powiedzie zwraca 0, jeżeli tak zwraca 1.

Tak więc nauczyliśmy się kontrolować tekst w kontrolce.

Style Edit'a

Kontrolka Edit posiada kilka styli, które znacznie zmieniają jej funkcjonalność.

ES_MULTILINE
Do tej pory mogliśmy zapisać ciąg znaków w jednej linijce. Styl ten powoduje, że kontrolka jest "wieloliniowa", dosłownie tłumacząc. W kontrolce możemy już zapisywać tekst w kolejnych linijkach. Uzyskamy efekt podobny do wpisywania tekstu w windowsowym notatniku.

ES_LEFT
Tekst w kontrolce będzie wyrównywany do prawej strony, jest to domyślnie stosowane.

ES_RIGHT
Jak wyżej, tyle, że do prawej.

ES_CENTER
Tekst będzie umieszczany na środku linii, co nazywa się wyśrodkowaniem tekstu.

ES_HSCROLL
Działa tylko z ES_MULTILINE, powoduje, że gdy wyjdziemy poza obszar kontrolki w poziomie podczas pisania, widok tekstu w kontrolce automatycznie będzie sie przesuwał.

ES_VSCROL
Działa tylko z ES_MULTILINE, powoduje, że gdy wyjdziemy poza obszar kontrolki w pionie podczas pisania, widok tekstu w kontrolce automatycznie będzie sie przesuwał.

WS_AUTOHSCROLL
Działa tylko z ES_MULTILINE, powoduje pojawienie się paska przewijania na dole kontrolki.

WS_AUTOVSCROL
Działa tylko z ES_MULTILINE, powoduje pojawienie się paska przewijania z prawej strony kontrolki.

ES_READONLY
Styl ten blokuje pisanie w kontrolce przez użytkownika. Kontrolka nadaje się tylko do odczytu.

ES_PASSWORD
Styl ten używamy do wpisywania haseł, powoduje, że zamiast liter pojawiają się gwiazdki(kropki).

Zmiana czcionki

Zmianę czcionki wykonuje się poprzez wysłanie komunikatu do samej kontrolki. Komunikat będziemy wysyłać funkcją SenMessage(). Jako pierwszy parametr podajemy uchwyt kontrolki do której wysyłamy komunikat. Drugi parametr to nazwa wysyłanego komunikatu, czyli dla zmiany czcionki WM_SETFONT. Trzeci to uchwyt do czcionki, na temat tworzenia czcionek będzie w dziale o GDI. Uchwyt ten rzutujemy na WPARAM. Jeżeli ostatni parametr będzie wynosił 1, zmiana zostanie odrazu zastosowana.

...
HFONT hFont=CreateFont(
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
"Arial"
);
SendMessage(hEdit,WM_SETFONT,(WPARAM)hFont,
1
);
...

Oczywiście przed zniszczeniem okna nalezy zwolnić utworzone w niej kontrolki funckją DestroyWindow(), podając jako parametr uchwyt do kontrolki.

Spójrzmy na przykład użycia kontrolki edit i przycisku:

#include <windows.h>
#include <commctrl.h>

HWND hEdit,hButton,hWnd;
HFONT hFont;
//uchwyt do czcionki

CHAR szClassName[]=
"OknoRodzica"
;
HINSTANCE* hInst;

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

INT WINAPI WinMain(HINSTANCE hInstance,HINSTANCE,LPSTR lStart,INT nShow)
{
  hInst=&hInstance;
  WNDCLASSEX wc;
  wc.hInstance=*hInst;
  wc.lpszClassName=szClassName;
  wc.lpfnWndProc=WndProc;
  wc.style=
0
;
  wc.cbSize=sizeof(WNDCLASSEX);
  wc.hIcon=LoadIcon(
0
,IDI_APPLICATION);
  wc.hIconSm=LoadIcon(
0
,IDI_APPLICATION);
  wc.hCursor=LoadCursor(
0
,IDC_ARROW);
  wc.lpszMenuName=
0
;
  wc.cbClsExtra=
0
;
  wc.cbWndExtra=
0
;
  wc.hbrBackground=(HBRUSH)COLOR_BACKGROUND;
  if(!RegisterClassEx(&wc)) return
0
;
  hWnd=CreateWindowEx(
0
,szClassName,
"Użycie edit'a"
,WS_OVERLAPPEDWINDOW,
20
,
20
,
600
,
300
,
0
,
0
,*hInst,
0
);
  ShowWindow(hWnd,nShow);
  MSG msgs;
  while(GetMessage(&msgs,
0
,
0
,
0
))
  {
    TranslateMessage(&msgs);
    DispatchMessage(&msgs);
  }
  return msgs.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wPar,LPARAM lPar)
{
  switch(msg)
  {
    case WM_CREATE:
      
//tworzymy kontrolkę edit

      hEdit=CreateWindowEx(WS_EX_CLIENTEDGE,WC_EDIT,
"Tu mozna cos napisac"
,
      WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_AUTOHSCROLL|ES_AUTOVSCROLL|WS_VSCROLL|WS_HSCROLL,
10
,
10
,
570
,
200
,hwnd,
      
0
,*hInst,
0
);
      
//ustawiamy czcionkę

      hFont=CreateFont(
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
"Arial"
);
      SendMessage(hEdit,WM_SETFONT,(WPARAM)hFont,
0
);
      
//tworzymy przycisk

      hButton=CreateWindowEx(
0
,WC_BUTTON,
"Wyczyść tekst w kontrolce"
,
      WS_CHILD|WS_VISIBLE,
10
,
220
,
570
,
40
,hwnd,(HMENU)
1
,*hInst,
0
);
      break;
    case WM_COMMAND:
      
//obsługa przycisku

      if(wPar==
1
) SetWindowText(hEdit,
""
);
      
//funkcją SetWindowText czyścimy tekst w kontrolce

      break;
    case WM_DESTROY:
//przed usunięciem okna

      DeleteObject(hFont);
//zwalniamy czcionkę

      DestroyWindow(hEdit);
//zwalniamy kontrolke edit

      DestroyWindow(hButton);
//zwalniamy przycisk

      PostQuitMessage(
0
);
      break;
    default:
      return DefWindowProc(hwnd,msg,wPar,lPar);
  }
  return
0
;
}

Po skompilowaniu powinniśmy mieć mniej-więcej taki program:

Jeszczę chcę zaznaczyć, że trzeba nauczyć się myśleć o kontrolkach trochę jak o oknach. Bo z kontrolkami możemy postępować jak z oknami(bo przecież są oknami). Możemy je minimalizować, chować, maksymalizować, wszystko tak jak z oknami, a wszystko funkcjami znanymi z okien, np. ShowWindow(hEdit,SW_MAXIMIZE).