[WinAPI] Ignorowanie komunikatu WM_LBUTTONDOWN / UP
Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?
Zarejestruj się!

[WinAPI] Ignorowanie komunikatu WM_LBUTTONDOWN / UP

AutorWiadomość
Temat założony przez niniejszego użytkownika
[WinAPI] Ignorowanie komunikatu WM_LBUTTONDOWN / UP
» 2017-11-14 20:39:20
Próbuję zrobić prosty program umożliwiający narysowanie prostokąta, koła lub trójkąta po kliknięciu myszy, przejechaniu do kolejnej współrzędnej i puszczeniu przycisku. Pomimo klikania odpowiedniego przycisku program ignoruje ten case i nie wywołuje funkcji rysowania. Błąd leży prawdopodobnie w WndProc(), ale nie potrafię go odnaleźć.

Kod całego programu:
C/C++
#include <windows.h>
#include <wchar.h>

LPCWSTR ClassName = TEXT( "Aplikacja testowa" );

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
void CreatePBs( HDC & hdc, HBRUSH * brush, HPEN * pen );
void DrawMenu( HWND hwnd, HDC & hdc, HBRUSH * brush, HPEN * pen, RECT & cr );
void Draw( HWND hwnd, int shape, BOOL transparent, HBRUSH * brush, HPEN * pen, int color, POINT & start, POINT & end );
int ChooseShape( POINT & cursor, int shape, RECT & cr );
int PickColor( POINT & cursor, int color, RECT & cr );

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
    MSG Komunikat;
    WNDCLASSEX wc = {
        sizeof( WNDCLASSEX ),
        CS_VREDRAW | CS_HREDRAW,
        WndProc,
        0,
        0,
        hInstance,
        0,
        LoadCursor( NULL, IDC_ARROW ),
        ( HBRUSH )( COLOR_WINDOW + 0 ),
        NULL,
        ClassName,
        0
    };
   
    if( !RegisterClassEx( & wc ) )
    {
        MessageBox( NULL, TEXT( "Błąd rejestracji tego okna!" ), TEXT( "Problem..." ),
        MB_ICONEXCLAMATION | MB_OK );
        return 1;
    }
   
    HWND hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, ClassName, TEXT( "Aplikacja testowa" ), WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT, 640, 490, NULL, NULL, hInstance, 0 );
   
    if( hwnd == NULL )
    {
        MessageBox( NULL, TEXT( "Błąd utworzenia okna." ), TEXT( "Problem..." ), MB_ICONEXCLAMATION );
        UnregisterClass( ClassName, hInstance );
        return 1;
    }
    ShowWindow( hwnd, nCmdShow );
    UpdateWindow( hwnd );
   
    while( GetMessage( & Komunikat, NULL, 0, 0 ) )
    {
        TranslateMessage( & Komunikat );
        DispatchMessage( & Komunikat );
    }
    UnregisterClass( ClassName, hInstance );
   
    return Komunikat.wParam;
}

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    PAINTSTRUCT ps;
    HDC hdc;
    RECT cr;
    HBRUSH brush[ 16 ];
    HPEN pen[ 16 ];
    int state = 0, shape, color;
    BOOL lBtnDwn = false, transparent = true;
    POINT start, end;
    switch( msg )
    {
    case WM_CLOSE:
        //if ( MessageBox( hwnd, TEXT( "Czy chcesz wyjść z programu?" ), TEXT(" Wyjście "), MB_ICONQUESTION | MB_YESNO ) == IDYES )
        DestroyWindow( hwnd );
        return 0;
    case WM_DESTROY:
        PostQuitMessage( 0 );
        break;
    case WM_PAINT:
        {
            hdc = BeginPaint( hwnd, & ps );
            CreatePBs( hdc, brush, pen );
            DrawMenu( hwnd, hdc, brush, pen, cr );
            EndPaint( hwnd, & ps );
            break;
        }
    case WM_GETMINMAXINFO:
        {
            LPMINMAXINFO lpMMI =( LPMINMAXINFO ) lParam;
            lpMMI->ptMinTrackSize.x = 300;
            lpMMI->ptMinTrackSize.y = 490;
            break;
        }
    case WM_MOUSEMOVE:
        {
            POINT cursor;
            GetCursorPos( & cursor );
            ScreenToClient( hwnd, & cursor );
            GetClientRect( hwnd, & cr );
            TCHAR buff[ 40 ];
            if(( cursor.x < cr.right - 100 ) &&( cursor.y < cr.bottom ) )
                 state = 1;
            else if(( cursor.x >= cr.right - 85 ) &&( cursor.y < 325 ) )
                 state = 2;
            else if(( cursor.y > 360 ) &&( cursor.y < 425 ) )
                 state = 3;
           
            swprintf_s( buff, 40, TEXT( "Paint (x: %d, y: %d), state: %d" ), cursor.x, cursor.y, state );
            SetWindowText( hwnd, buff );
            break;
        }
    case WM_LBUTTONDOWN:
        {
            POINT cursor;
            GetCursorPos( & cursor );
            ScreenToClient( hwnd, & cursor );
            if( state == 2 )
            {
                color = PickColor( cursor, color, cr );
                transparent = false;
            }
            if( state == 3 )
                 shape = ChooseShape( cursor, shape, cr );
           
            if( !lBtnDwn && state == 1 )
            {
                lBtnDwn = true;
                GetCursorPos( & start );
                ScreenToClient( hwnd, & start );
            }
            break;
        }
    case WM_LBUTTONUP:
        {
            HDC hdc = GetDC( hwnd );
            CreatePBs( hdc, brush, pen );
            GetCursorPos( & end );
            ScreenToClient( hwnd, & end );
            if( state == 1 ) Draw( hwnd, shape, transparent, brush, pen, color, start, end );
           
            ReleaseDC( hwnd, hdc );
            lBtnDwn = false;
            break;
        }
        default:
        return DefWindowProc( hwnd, msg, wParam, lParam );
    }
   
    return 0;
}

void CreatePBs( HDC & hdc, HBRUSH * brush, HPEN * pen )
{
    COLORREF color[ 16 ] =
    {
        0x000000, 0x777777,
        0x000080, 0x0000FF,
        0x004000, 0x00FF00,
        0x008080, 0x00FFFF,
        0x800000, 0xFF0000,
        0x800040, 0xFF00FF,
        0x808040, 0xFFFF00,
        0x806060, 0xFFFFFF
    };
   
   
    for( int i = 0; i < 16; i++ )
    {
        brush[ i ] = CreateSolidBrush( color[ i ] );
        pen[ i ] = CreatePen( PS_SOLID, 1, color[ i ] );
    }
}

void DrawMenu( HWND hwnd, HDC & hdc, HBRUSH * brush, HPEN * pen, RECT & cr )
{
   
   
    enum colors { black, gray, darkred, red, darkgreen, green,
        darkyellow, yellow, darkblue, blue, purple, pink,
        seal, lightblue, darkgray, white };
   
    HBRUSH bkMenu = CreateSolidBrush( 0xC0C0C0 );
   
    HBRUSH OldBrush =( HBRUSH ) SelectObject( hdc, brush[ white ] );
    HPEN OldPen =( HPEN ) SelectObject( hdc, pen[ black ] );
   
    //Rysowanie dużej ramki
    GetClientRect( hwnd, & cr );
    Rectangle( hdc, cr.left, cr.top, cr.right, cr.bottom );
   
    //Rysowanie małej ramki
    SelectObject( hdc, bkMenu );
    SelectObject( hdc, pen[ blue ] );
    Rectangle( hdc, cr.right - 100, 1, cr.right - 1, cr.bottom - 1 );
   
    for( int i = 0; i < 16; i++ )
    {
        SelectObject( hdc, pen[ i ] );
        SelectObject( hdc, brush[ i++ ] );
        Rectangle( hdc, cr.right - 85, 20 * i + 25, cr.right - 60, 20 * i + cr.top );
        SelectObject( hdc, pen[ i ] );
        SelectObject( hdc, brush[ i ] );
        Rectangle( hdc, cr.right - 40, 20 * i + 25, cr.right - 15, 20 * i + cr.top );
    }
   
    SelectObject( hdc, pen[ black ] );
    for( int i = 0; i < 2; i++ )
    {
        Rectangle( hdc, cr.right - 85, 40 * i + 360, cr.right - 60, 40 * i + 385 );
        Rectangle( hdc, cr.right - 40, 40 * i + 360, cr.right - 15, 40 * i + 385 );
    }
   
    POINT triangle[ 3 ] = { { cr.right - 35, 365 }, { cr.right - 20, 365 }, { cr.right - 28, 380 } };
    Polygon( hdc, triangle, 3 );
    for( int i = 0; i < 3; i++ )
    {
        triangle[ i ].y += 40;
    }
    SelectObject( hdc, brush[ black ] );
    Polygon( hdc, triangle, 3 );
    Rectangle( hdc, cr.right - 80, 365, cr.right - 65, 380 );
    Ellipse( hdc, cr.right - 80, 405, cr.right - 65, 420 );
   
   
    //Usuwanie obiektów GDI
    for( int i = 0; i < 16; i++ )
    {
        DeleteObject( brush[ i ] );
        DeleteObject( pen[ i ] );
    }
    DeleteObject( bkMenu );
}

void Draw( HWND hwnd, int shape, BOOL transparent, HBRUSH * brush, HPEN * pen, int color, POINT & start, POINT & end )
{
    HDC hdc = GetDC( hwnd );
    if( !transparent )
    {
        SelectObject( hdc, brush[ color ] );
        SelectObject( hdc, pen[ color ] );
    }
    else
    {
        SelectObject( hdc, GetStockObject( NULL_BRUSH ) );
        SelectObject( hdc, pen[ color ] );
    }
   
    switch( shape )
    {
    case 1:
        {
            Rectangle( hdc, start.x, start.y, end.x, end.y );
        }
        break;
    case 2:
        {
            Ellipse( hdc, start.x, start.y, end.x, end.y );
        }
        break;
    case 3:
        {
            SelectObject( hdc, GetStockObject( NULL_BRUSH ) );
            POINT point[ 3 ] = { { start.x, start.y }, { end.x, end.y }, { end.x, start.y } };
            Polygon( hdc, point, 3 );
        }
        break;
    case 4:
        {
            POINT point[ 3 ] = { { start.x, start.y }, { end.x, end.y }, { end.x, start.y } };
            Polygon( hdc, point, 3 );
        }
        break;
        default:
        return;
    }
    ReleaseDC( hwnd, hdc );
}

int ChooseShape( POINT & cursor, int shape, RECT & cr )
{
    int Shape = shape;
    if(( cursor.x >=( cr.right - 85 ) ) &&( cursor.x <=( cr.right - 60 ) ) &&( cursor.y >= 395 ) &&( cursor.y <= 420 ) )
         Shape = 1;
    else if(( cursor.x >=( cr.right - 85 ) ) &&( cursor.x <=( cr.right - 60 ) ) &&( cursor.y >= 435 ) &&( cursor.y <= 460 ) )
         Shape = 2;
    else if(( cursor.x >=( cr.right - 40 ) ) &&( cursor.x <=( cr.right - 15 ) ) &&( cursor.y >= 395 ) &&( cursor.y <= 420 ) )
         Shape = 3;
    else if(( cursor.x >=( cr.right - 40 ) ) &&( cursor.x <=( cr.right - 15 ) ) &&( cursor.y >= 435 ) &&( cursor.y <= 460 ) )
         Shape = 4;
   
    return Shape;
}

int PickColor( POINT & cursor, int color, RECT & cr )
{
    enum colors { black, gray, darkred, red, darkgreen, green,
        darkyellow, yellow, darkblue, blue, purple, pink,
        seal, lightblue, darkgray, white };
    int Color = color;
    for( int i = 0; i < 16; i++ )
    {
        if(( cursor.x >=( cr.right - 85 ) ) &&( cursor.x <=( cr.right - 60 ) ) &&( cursor.y >=( 20 * i + 25 ) ) &&( cursor.y <=( 20 * i + cr.top ) ) )
             Color = i++;
       
        if(( cursor.x >=( cr.right - 40 ) ) &&( cursor.x <=( cr.right - 15 ) ) &&( cursor.y >=( 20 * i + 25 ) ) &&( cursor.y <=( 20 * i + cr.top ) ) )
             Color = i;
       
    }
    return Color;
}
P-166885
» 2017-11-14 20:59:38
Zmienna state ma wartość zero, zmienna lBtnDwn false, więc nic dziwnego, że nic się nie dzieje. To są zmienne automatyczne, nie pamiętają one swoich wartości pomiędzy wywołaniami funkcji.
P-166886
Temat założony przez niniejszego użytkownika
» 2017-11-14 21:38:07
To jak to rozwiązać nie używając zmiennych globalnych?
P-166890
» 2017-11-15 12:03:47
Użyć klas.
P-166895
Temat założony przez niniejszego użytkownika
» 2017-11-15 13:45:42
@Monika90 Doczytałem i użyłem zmiennych statycznych, dziękuję za naprowadzenie.

@kmlkamilek
No właśnie dlatego miałem problem, bo klasy mniej więcej rozumiem, ale zapomniałem jak się to robi w proceduralnym.
P-166896
« 1 »
 Strona 1 z 1