Skocz do zawartości

Zablokowane [C++, WinAPI] Wciśnięty button


Rudy

Rekomendowane odpowiedzi

Witam!

 

Mam pewien problem w WinAPI. Chciałbym, żeby po kliknięciu na button (kontrolkę) została ona wciśnięta. Przeszukałem MSDN i znalazłem parę funkcji, ogólnie mój kod operujący kontrolkami wygląda tak:

 

__________________________________________________

// --= Plik nagłówkowy =--

enum GAMESTATE

{

Stop = 7,

Play = 8,

Pause = 9,

Frame = 10

};

 

// --= Plik z funkcjami =--

#define WINDOWS_LEAN_AND_MEAN

#include <windows.h>

#include <windowsx.h>

#include "header.h"

 

GAMESTATE state = Stop;

HWND ctrl [11]; // tablica z uchwytami kontrolek (te buttony to przedział 7-10)

HICON img_butt [4]; // tablica z obrazkami

 

LRESULT CALLBACK MainWinProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

{

switch (msg)

{

case WM_CREATE:

{

HINSTANCE hInst = GetModuleHandle (NULL);

 

// wczytywanie obrazków

img_butt[0] = (HICON) LoadImage (hInst, "resources\\butt_rev.ico", IMAGE_ICON, 16, 16, LR_LOADFROMFILE);

img_butt[1] = (HICON) LoadImage (hInst, "resources\\butt_play.ico", IMAGE_ICON, 16, 16, LR_LOADFROMFILE);

img_butt[2] = (HICON) LoadImage (hInst, "resources\\butt_pause.ico", IMAGE_ICON, 16, 16, LR_LOADFROMFILE);

img_butt[3] = (HICON) LoadImage (hInst, "resources\\butt_frame.ico", IMAGE_ICON, 16, 16, LR_LOADFROMFILE);

 

// tworzenie kontrolek

ctrl[ 7] = CreateWindowEx (NULL, "BUTTON", NULL, WS_CHILD | WS_VISIBLE | BS_ICON, 10, 450, 22, 22, hwnd, NULL, hInst, NULL);

ctrl[ 8] = CreateWindowEx (NULL, "BUTTON", NULL, WS_CHILD | WS_VISIBLE | BS_ICON, 49, 450, 22, 22, hwnd, NULL, hInst, NULL);

ctrl[ 9] = CreateWindowEx (NULL, "BUTTON", NULL, WS_CHILD | WS_VISIBLE | BS_ICON, 88, 450, 22, 22, hwnd, NULL, hInst, NULL);

ctrl[10] = CreateWindowEx (NULL, "BUTTON", NULL, WS_CHILD | WS_VISIBLE | BS_ICON, 127, 450, 22, 22, hwnd, NULL, hInst, NULL);

 

// ustawianie właściwości (pokrywa sie z funkcjami wykonywanymi przy wciśnięciu ctrl[7])

Button_SetState (ctrl[ 7], TRUE);

Button_Enable (ctrl[ 9], FALSE);

 

// dodanie obrazków do przycisków

SendMessage (ctrl[ 7], BM_SETIMAGE, IMAGE_ICON, (LPARAM)img_butt[0]);

SendMessage (ctrl[ 8], BM_SETIMAGE, IMAGE_ICON, (LPARAM)img_butt[1]);

SendMessage (ctrl[ 9], BM_SETIMAGE, IMAGE_ICON, (LPARAM)img_butt[2]);

SendMessage (ctrl[10], BM_SETIMAGE, IMAGE_ICON, (LPARAM)img_butt[3]);

}

case WM_COMMAND:

{

// --= podział na poszczególne kontrolki (switch nie chce współpracować z wartościami w tablicy)

int i = -1;

for (int _i = 0; _i < 11; ++_i)

if ((HWND)lParam == ctrl[_i]) i = _i;

 

// przyciski

if (i >= 7 && i < 11)

switch (HIWORD(wParam))

{

case BN_CLICKED:

if (state != Frame) Button_SetState (ctrl[state], FALSE);

state = static_cast<GAMESTATE> (i);

Button_Enable (ctrl[ 9], i!=7);

Button_Enable (ctrl[10], i!=8);

if (state != Frame)

Button_SetState (ctrl[state], TRUE);

// MessageBox (NULL, "ClicK!!!", tostr(i), NULL);

if (state == Frame) SendMessage (ctrl[9], BM_CLICK, 0, 0);

break;

}

}

break;

case WM_DESTROY:

// usuwanie ikonek

DestroyIcon (img_butt[0]);

DestroyIcon (img_butt[1]);

DestroyIcon (img_butt[2]);

DestroyIcon (img_butt[3]);

 

PostQuitMessage (0);

break;

default:

return DefWindowProc (hwnd, msg, wParam, lParam);

}

return 0;

}

__________________________________________________

 

Button_Set_State ustawia wciśnięcie przycisku.

Button_Enable ustawia aktywność (można kliknąć, lub nie, coś jak przycisk zatrzymania w przeglądarce po wczytaniu strony).

ctrl[7] to przycisk "Stop". Dezaktywuje tylko przycisk "Pause".

ctrl[8] to przycisk "Play". Dezaktywuje tylko przycisk "Frame".

ctrl[9] to przycisk "Pause". Aktywuje wszystkie przyciski.

ctrl[10] to tzw. przycisk "Frame" (przesunięcie o jedną klatkę). Jako jedyny nie ma pozostać wciśnięty po kliknięciu. Po użyciu wywołuje przycisk "Pause" (ta funkcja później powędruje gdzie indziej).

 

No to teraz opiszę problem :) . Teoretycznie wszystko powinno działać, ale jest parę niedociągnięć:

- Gdy wciśniemy LPM wciśnięty button, odjedziemy myszką i puścimy LPM, button staje się zwykłym, niewciśniętym przyciskiem.

- Wciśnięcie przycisku "Frame" symuluje wciśnięcie Pause, mimo to Pause nie pozostaje wciśnięte.

- Każde wciśnięcie przycisku (poza Frame) wywołuje jego wciśnięcie dwukrotnie. Winowajcą jest tutaj Button_Set_State (... TRUE). gdy zmienia on wartość z FALSE na TRUE symuluje ponowne wciśnięcie przycisku (nie wiadomo czemu).

 

Ma ktoś pomysł jak zaradzić tym problemom?

Odnośnik do komentarza
Udostępnij na innych stronach

WinAPI + Cpp to masochizm. Polecam wxWidgets lub język C#, który jest wprost stworzony do takich wyczynów.

Ale jak Ci zależy to:

1. Tak raczej powinno być... Sprawdź sobie inne aplikacje.

2. Poczytaj o GDI, czyści-rysuje ten region clienta, który jest tego wart.

3. To akurat twój błąd, a nie WinAPI.

Odnośnik do komentarza
Udostępnij na innych stronach

Zostanę jednak przy C++. Uczę się WinAPI, bo podobno podstawy są wymagane do Direct. A poza tym lubię aplikacje okienkowe :sp_ike:

 

No tak, raczej powinny "odskakiwać". Myślałem, żeby zrobić w ten sposób bo mniej miejsca zajmuje w przestrzeni roboczej, no ale skoro nie ma takiej możliwości, zrobię to inaczej. Pozostałe dwa problemy były zależne od pierwszego, skoro zmieniam sposób, problemy same znikną. Dzięki za pomoc, zamykam.

Odnośnik do komentarza
Udostępnij na innych stronach

Gość
Ten temat został zamknięty. Brak możliwości dodania odpowiedzi.
  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...