WinApi przycisk i Listbox

0

Bez przeciągania, mam problem z WinApi.

  1. Jak przypisać działanie przyciskowi.

A teraz trochę szerzej:

Mam 3 rzeczy w oknie:
Listbox, Edit i Button.
W "EDIT" użytkownik ma wpisać nazwę pliku txt do którego wpisze zawartość Listbox'u. Wykona się to po wciśnięciu przycisku Button.

  1. Program ma przez skan barcode'u wpisać do Listboxa zeskanowany code.

Jestem nowy w temacie WinApi więc jakbyście dosyć jasno pisali co gdzie wpisać, albo pokierować było by miło.

0
#include <windows.h>

#define ID_BUTTON 1
#define ID_LISTBOX 2

/// w funkcji WinMain()
hButton = CreateWindowEx(..., (HMENU)ID_BUTTON, ...);
hListBox = CreateWindowEx(..., (HMENU)ID_LISTBOX, ...);
hEdit = ...;

/// w Procedurze glownego okna

case WM_COMMAND:{
    switch(wParam)
    {
        case ID_BUTTON:{
             /// pobieramy tekst z kontrolki i zapisujemy w lancuchu cText
            unsigned int iSize = GetWindowTextLength(hEdit);
            char cText = new char[iSize+1];
            GetWindowText(hEdit, cText, iSize+1); /// +1 dla znaku /0
             /// otwieramy plik
            // http://cpp0x.pl/kursy/Kurs-WinAPI-C++/Podstawy/Pliki/180
            delete cText;
            for(int it=0; it<SendMessage(hListBox, LB_GETCOUNT, 0, 0); ++it)
            {
                iSize = SendMessage(hListBox, LB_GETTEXTLEN, 0, 0);
                cText = new char[iSize+1];
                SendMessage(hListBox, LB_GETTEXT, it, (LPARAM)cText);
                /// zapisujemy wartosc cText (tekstu it - indexu listy) do pliku
                delete cText;
            }
            /// zamykamy plik tekstowy
            break;
        }
    }
    break;
}
 

Jak czegoś nie rozumiesz, pisz

0

Jeśli mam coś takiego:

 
hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, NazwaKlasy, "Okno", WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT, 200, 250, NULL, NULL, hInstance, NULL );

to

case WM_COMMAND:{
    switch(wParam)
    {
        case ID_BUTTON:{
             /// pobieramy tekst z kontrolki i zapisujemy w lancuchu cText
            unsigned int iSize = GetWindowTextLength(hEdit);
            char cText = new char[iSize+1];
            GetWindowText(hEdit, cText, iSize+1); /// +1 dla znaku /0
             /// otwieramy plik
            // http://cpp0x.pl/kursy/Kurs-WinAPI-C++/Podstawy/Pliki/180
            delete cText;
            for(int it=0; it<SendMessage(hListBox, LB_GETCOUNT, 0, 0); ++it)
            {
                iSize = SendMessage(hListBox, LB_GETTEXTLEN, 0, 0);
                cText = new char[iSize+1];
                SendMessage(hListBox, LB_GETTEXT, it, (LPARAM)cText);
                /// zapisujemy wartosc cText (tekstu it - indexu listy) do pliku
                delete cText;
            }
            /// zamykamy plik tekstowy
            break;
        }
    }
    break;
}
 

Mam dać pod tym pierwszym w "{}" czy może inaczej?
I jeśli mam button i całą resztę niżej, to nie przeszkadza to w tym?

1

Nie rozumiem o jakich klamrach chodzi, ale wnioskuję, że o switch - case
Zapis dowolny:

int main()
{
    int n;
    switch(n)
    {
        case 1:{
            break;
        }
        case 2:{
            break;
        }
        case 3:
            break;
        case 4:
        case 5:
            break;
    }
}
 

Ogólnie polecam do WinAPI ten kurs http://cpp0x.pl/kursy/Kurs-WinAPI-C++/Podstawy/Podstawy-WinAPI/168
Tutaj mały przykład: http://pastebin.com/7H1Zcbqw

Troszkę teorii na koniec:

  1. Funkcja WinMain() rozpoczyna Twój program tak jak funkcja main()
    a) Tworzysz tam wszystkie kontrolki
    b) Przypisujesz zmiennym startowe wartości
    c)
while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    } 

To jest pętla komunikatu. Wszystko, co sie zdarzy jest odkodowywane i przesyłane do odpowiedniego okienka (o tym za chwilę)

  1. Podstawowe informacje o oknie:
    a) okno posiada swój uchwyt (HWND) i jest nim przycisk, edit, listbox, główne okno itp. W zasadzie cały świat składa się z okien...
    b) każde okno posiada swojego okno-rodzica, do którego wysyłane są wszystkie komunikaty związane z jakąś akcją np. wciśnięcie przycisku.
    c) do identyfikacji okna można używać uchwytu bądź identyfikatora.
    d) identyfikator przypisujemy przy tworzeniu okna w funkcji CreateWindowEx() (3 od końca argument)
#define ID_BUTTON 1
hButton = CreateWindowEx(0, "BUTTON", "Zapisz", WS_CHILD | WS_VISIBLE, 0, 315, 200, 21, hwnd, (HMENU)ID_BUTTON, hThisInstance, NULL);
 

e) każde okno posiada swoją pętlę komunikatów (procedurę). Twoje okno główne (hwnd) posiada procedurę o nazwie WindowProcedure. Tam trafiają wszelkie komunikaty związane z oknem hwnd oraz kontrolkami, które utworzył. W funkcji CreateWindowEx() jednym z parametrów jest podanie okna-rodzica.
f) Jeżeli wciśniesz np. przycisk wyśle on do kontrolki nadrzędnej (do rodzica) komunikat składający się z 3 wartości:

  • message
  • wParam
  • lParam
    Jeżeli chodzi akurat o samo wciśnięcie przycisku:
  • message == WM_COMMAND
  • wParam == ID KONTROLKI KTÓRA WYSYŁA KOMUNIKAT
  • lParam == UHWYT DO TEJŻE KONTROLKI
    g) Do odczytywania komunikatu służy nam:
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  
    {
        /// tutaj sprawdzamy wartość message
    }
    return 0;
} 

Nas interesuje wciśnięty przycisk, więć sprawdzamy WM_COMMAND

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  
    {
        case WM_COMMAND:{
            /// Tu !!!
            break;
        }
    }
    return 0;
} 

No dobrze. Ale wiele kontrolek wysyła nam wiaomość WM_COMMAND. Jak sprawdzić, że to akurat ta kontrolka o którą nam chodzi? Posłużymy się identyfikatorem przypisanym w fazie tworzenia przycisku przesyłanym w wartości wParam:

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  
    {
        case WM_COMMAND:{
            switch(wParam)
            {
                 case ID_BUTTON:
                      /// to co wpiszesz tu, zdarzy się po wciśnięciu przycisku o identyfikatorze ID_BUTTON
                      break;
            }
            break;
        }
    }
    return 0;
} 

Jak czegoś nie rozumiesz pisz dalej.

0

Tak więc:
Screen z błedami w załączniku.
A tutaj daje kod, może ktoś coś..

#include <fstream>
#include <string>
#include <windows.h>
#include <iostream>
#include <cstdlib>

LPSTR NazwaKlasy = "Klasa Okienka";
MSG Komunikat;
HWND g_hPrzycisk;
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );

void tworzenie_pliku(char nazwa_pliku, std::string kod){
	std::ofstream plik( nazwa_pliku+".txt" ); 
    plik << kod ;
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
    
    // WYPEŁNIANIE STRUKTURY
    WNDCLASSEX wc;
    
    wc.cbSize = sizeof( WNDCLASSEX );
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
    wc.hCursor = LoadCursor( NULL, IDC_ARROW );
    wc.hbrBackground =( HBRUSH )( COLOR_WINDOW + 1 );
    wc.lpszMenuName = NULL;
    wc.lpszClassName = NazwaKlasy;
    wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
    
    // REJESTROWANIE KLASY OKNA
    if( !RegisterClassEx( & wc ) )
    {
        MessageBox( NULL, "Odmawia rejestracji tego okna!", "Niestety...",
        MB_ICONEXCLAMATION | MB_OK );
        return 1;
    }
    
    // TWORZENIE OKNA
    HWND hwnd;
    //okno
    hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, NazwaKlasy, "Okno", WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT, 200, 250, NULL, NULL, hInstance, NULL );
    case WM_COMMAND:{
    switch(wParam)
    {
        case ID_BUTTON:{
             /// pobieramy tekst z kontrolki i zapisujemy w lancuchu cText
            unsigned int iSize = GetWindowTextLength(hEdit);
            char cText = new char[iSize+1];
            GetWindowText(hEdit, cText, iSize+1); /// +1 dla znaku /0
             /// otwieramy plik
            // http://cpp0x.pl/kursy/Kurs-WinAPI-C++/Podstawy/Pliki/180
            delete cText;
            for(int it=0; it<SendMessage(hListBox, LB_GETCOUNT, 0, 0); ++it)
            {
                iSize = SendMessage(hListBox, LB_GETTEXTLEN, 0, 0);
                cText = new char[iSize+1];
                SendMessage(hListBox, LB_GETTEXT, it, (LPARAM)cText);
                /// zapisujemy wartosc cText (tekstu it - indexu listy) do pliku
                delete cText;
            }
            /// zamykamy plik tekstowy
            break;
        }
    }
    break;
}
	//koniec okno
    
	//przycisk
    g_hPrzycisk = CreateWindowEx( 0, "BUTTON", "Zapisz", WS_CHILD | WS_VISIBLE,
		100, 150, 60, 30, hwnd, NULL, hInstance, NULL );
	/* 
	case WM_COMMAND:
		{
		    if( HIWORD( wParam ) == BN_CLICKED )
		    {
		        char buf[ 255 ];
		        wsprintf( buf, "Wciśnięty przycisk o identyfikatorze %hu.", LOWORD( wParam ) );
		        MessageBox( hwnd, buf, "Test", MB_ICONINFORMATION );
		    }
		}
		break;	
	*/
	//koniec przycisk
	
	//poletextowe
	HWND hText = CreateWindowEx( 0, "EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 15, 150, 60, 30,
		hwnd, NULL, hInstance, NULL );	
	SetWindowText( hText, "Wpisz" );
	DWORD dlugosc = GetWindowTextLength( hText );
	LPSTR Bufor =( LPSTR ) GlobalAlloc( GPTR, dlugosc + 1 );
	GetWindowText( hText, Bufor, dlugosc + 1 );	
	//koniec pole tekstowe
	
    //okienko gdzie ma byc code.
	HWND hText1 = CreateWindowEx( WS_EX_CLIENTEDGE, "LISTBOX", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER |
	WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL, 15, 15, 150, 100, hwnd, NULL, hInstance, NULL );
    
    
    
	if( hwnd == NULL )
    {
        MessageBox( NULL, "Okno odmówiło!", "Ale kicha...", MB_ICONEXCLAMATION );
        return 1;
    }
    
    ShowWindow( hwnd, nCmdShow ); // Pokaż okienko...
    UpdateWindow( hwnd );
    
    // Pętla komunikatów
    while( GetMessage( & Komunikat, NULL, 0, 0 ) )
    {
        TranslateMessage( & Komunikat );
        DispatchMessage( & Komunikat );
    }
    return Komunikat.wParam;
}

// OBSŁUGA ZDARZEŃ
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
    case WM_CLOSE:
        DestroyWindow( hwnd );
        break;
        
    case WM_DESTROY:
        PostQuitMessage( 0 );
        break;
        
        default:
        return DefWindowProc( hwnd, msg, wParam, lParam );
    }
    
    return 0;
} 
0

Przejrzyj cały artykuł który napisałem i popraw błędy sam, bo teraz czuję jakbym napracował się na darmo. ok? :( Tam jest wszystko napisane. Ogarniasz if(), switch(), for(), while() i inne podstawy?

0

Ta podstawy ogarniam, tylko głupieje jak widze full code'u w winapi i nie wiem co gdzie dać itp.

Sorry, ale nie zauwazylem tego duzego posta, i go nie przeczytalem. Ale juz sie zabieram za czytanie!

0

Dam Ci radę, nie wchodź do puszczy bez kompasu i mapy (dosłownie i w przenośni).
Zapoznaj się z każdą funkcją, jej parametrami itp. Wszystko masz w dokumentacji.
https://msdn.microsoft.com/pl-pl/library/windows/desktop/ms632680%28v=vs.85%29.aspx
jak to przeczytasz pracując z kursem rozwiązania problemu same Ci przyjdą do głowy i w razie nie działania czegoś pisz :)

poprawione: http://pastebin.com/NJP1YNvP
ps. Nie wklejaj tego kodu bezsensownie tylko przeanalizuj co było źle w Twoim. Jak chcesz zacząć WinAPI poczytaj o wskaźnikach, typach danych, i czytaj do rzesz jego przede wszystkim dokumentację.

1 użytkowników online, w tym zalogowanych: 0, gości: 1