Autor Wątek: [WinAPI] Guzik z grafiką i tekstem  (Przeczytany 2980 razy)

Offline .Dexter.

  • Użytkownik

# Marzec 18, 2009, 17:04:55
Cześć.

Jako, że nie miałem z WinAPI nigdy styczności, pojawia się teraz masa problemów. Wczoraj zachciało mi się stworzenia przycisku z grafiką (align_left) i napisem. Poszperałem po MSDN i znalazłem to czego mi trzeba, ale nie potrafię do końca z tego skorzystać...

Otóż:
- tworzę przycisk,
- wczytuje bitmape,
- tworzę listę ImageList,
- dodaję bitmapę do listy (http://msdn.microsoft.com/en-us/library/ms909786.aspx),
- wypełniam strukturę BUTTON_IMAGELIST (http://msdn.microsoft.com/en-us/library/bb775953(VS.85).aspx) tutaj problem z uAlign, bo te makra które podaje MSDN nie są odnajdywane w "Commctrl.h",
- próbuję wywołać funkcję Button_SetImagelist() (http://msdn.microsoft.com/en-us/library/bb761867(VS.85).aspx) która też nie jest odnajdywana (Button_SetImageList' undeclared (first use this function) ),

Podejrzewam, że problemem może być to:
"Note  To use this API, you must provide a manifest specifying Comclt32.dll version 6.0. For more information on manifests, see Enabling Visual Styles."

Piszę to w Dev-C++ więc szukałem Comclt32.a albo .lib, ale znalazłem tylko Comctl32.a a to chyba coś innego. Poza tym, nie mam pojęcia jak dołączyć ten manifest i czy to w ogóle potrzebne.

A może da się jakoś prościej to zrobić?

Pozdrawiam :)

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline kafor7

  • Użytkownik

# Marzec 18, 2009, 17:27:05
w devie masz biblioteki z rozszerzeniem *.a w visualu masz *.lib.. jak nie wiesz co z tym zrobić to poczytaj o statycznym linkowaniu bibliotek

Offline .Dexter.

  • Użytkownik

# Marzec 18, 2009, 17:36:05
Zlinkowałem przecież. Zwróć uwagę na nazwy tych bibliotek. Ta która jest różni się od tej z MSDN.

Offline mosowski

  • Użytkownik

# Marzec 18, 2009, 17:45:32
Hmm Dev C++ korzysta z lunixowego GCC, więc nazwa będzie nie ComCtl32.lib, a libcomctl32.a lub lcomstrl32.a. Pod Windowsem zdecydowanie lepiej użyć Visual C++, więc pomyśl o przesiadce.
« Ostatnia zmiana: Marzec 18, 2009, 17:49:07 wysłana przez Szatan Wcielony »

Offline .Dexter.

  • Użytkownik

# Marzec 18, 2009, 17:51:34
Wierz mi, że myślałem, ale sporo korzystam z kursu Złośliwca, z którym mi się Visual kłóci niezmiernie.
Ok, zatem to jest dobry lib. Przyczyną może być ten manifest? Bo mimo zlinkowania tego Comctl32.a nic się nie zmienia...

OK pokombinowałem, przesiadłem się na Visual Studio, kod się kompiluje w porządku, ale obrazka ni ma. A w logach pustka...

#include "stdafx.h"
#include "asd.h"
#include "Commctrl.h"

LPSTR NazwaKlasy = "Klasa Okienka";
MSG Komunikat;
HWND guzik;
HBITMAP obraz,maska;
HIMAGELIST lista;
BUTTON_IMAGELIST bi;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
obraz = (HBITMAP)LoadImage(NULL, "c:\\plik.bmp", IMAGE_BITMAP, 32, 32, LR_LOADFROMFILE);
maska = (HBITMAP)LoadImage(NULL, "c:\\maska.bmp", IMAGE_BITMAP, 32, 32, LR_LOADFROMFILE);

//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_BACKGROUND);
 wc.lpszMenuName = NULL;
 wc.lpszClassName = NazwaKlasy;
 wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

//REJESTROWANIE KLASY OKNA
 if(!RegisterClassEx(&wc))
 {
  MessageBox(NULL, "Rejestracja okna nie powiodla sie.", "Error", MB_ICONEXCLAMATION | MB_OK);
   return 1;
 }

//TWORZENIE OKNA
 HWND hwnd;

 hwnd = CreateWindowEx(0, NazwaKlasy, "Okienko", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 400, 400, NULL, NULL, hInstance, NULL);

 if(hwnd==NULL)
 {
  MessageBox(NULL, "Okno sie nie pojawilo.", "Error", MB_ICONEXCLAMATION);
  return 1;
 }

guzik = CreateWindowEx(0, "BUTTON", "Guzik", WS_CHILD | WS_VISIBLE, 150, 150, 150, 30, hwnd, NULL, hInstance, NULL);
 
lista=ImageList_Create(32,32,ILC_MASK | ILC_COLOR24,1,0);
if(!lista)
{
MessageBox(hwnd,"Blad z tworzeniem listy.","asd",MB_ICONINFORMATION);
}

 ImageList_Add(lista,obraz,maska);
 
 bi.himl = lista;
         bi.uAlign = BUTTON_IMAGELIST_ALIGN_LEFT;
         bi.margin.top = 3;
         bi.margin.bottom = 3;
         bi.margin.left = 3;
         bi.margin.right = 3;

Button_SetImageList(guzik,lista);



DeleteObject(obraz);
 DeleteObject(maska);
 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;
}

Post pod postem, ale wciąż się z tym męczę... Nikt nie tworzył nigdy przycisku z grafiką i tekstem?
Czytałem też o innych funkcjach, np. można wysłać do guzika BM_SETIMAGE ale w komentach na MSDN piszą, że na Windows XP chyba nie da się za pomocą tego zrobić takiego guziczka - albo grafika albo tekst :/

// Edit by Riddlemaster: mocno zalecane jest niepisanie 3 postów jeden pod drugim w ciągu tak krótkiego czasu. Bez względu na powody.
Połączyłem, ale ostrzegam na przyszłość.
« Ostatnia zmiana: Marzec 23, 2009, 23:36:53 wysłana przez Riddlemaster »

Offline .Dexter.

  • Użytkownik

# Czerwiec 22, 2009, 11:25:21
Jako iż temat jest już stary to go trochę odkopię, żebyście mogli go zauważyć.
Wciąż tego problemu nie rozwiązałem, zostawiłem go praktycznie na koniec razem z innym (zmiana koloru tekstu w kontrolce EDIT).

Otóż doszedłem do wniosku, że nie da się tego zrobić bez tworzenia nowej kontrolki (czego zrobić nie potrafię, a jedynie mogę popsuć windowsowe :-\). Lub też można zrobić ikonę, na której będzie obrazek i tekst bo obsługuje przezroczystość i to byłoby super, ale jak ustawię guzikowi styl bs_icon to wtedy manifest na niego nie działa i wygląda brzydko.
No i ostatni sposób: rysować guzik ze stylem BS_OWNERDRAW i potem w odpowiednim komunikacie to wszystko malować, niestety tego też nie potrafię zrobić :-\

Znalazłem coś takiego: http://www.codeproject.com/KB/buttons/nativewin32xpthemes.aspx
Tyle, że ja w WinAPI jestem początkujący i nie czaję czegoś takiego jak rysowanie kontrolek z resource, tak jak to tutaj jest chyba zrobione...

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Czerwiec 22, 2009, 13:04:21
Cytuj
No i ostatni sposób: rysować guzik ze stylem BS_OWNERDRAW i potem w odpowiednim komunikacie to wszystko malować, niestety tego też nie potrafię zrobić :/
Odpowiednim komunikatem jest WM_DRAWITEM. MSDN ma odpowiedzi na wszystko:
http://msdn.microsoft.com/en-us/library/bb775923(VS.85).aspx
(polecam zajrzeć do opisu DRAWITEMSTRUCT i kolejnych)

W skrócie: dostajesz HDC i RECT, pozostaje już tylko coś namazać we wskazanym obszarze przy użyciu tego HDC. :)

Offline .Dexter.

  • Użytkownik

# Czerwiec 22, 2009, 13:14:52
A nie trzeba całego guzika odmalowywać? Wystarczy np. BitBlt?

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Czerwiec 22, 2009, 13:24:29
A nie trzeba całego guzika odmalowywać? Wystarczy np. BitBlt?
Trzeba. BitBlt wystarczy w momencie, gdy masz gotowy obrazek z całym guzikiem. :)

Offline .Dexter.

  • Użytkownik

# Czerwiec 22, 2009, 13:26:33
Właśnie z namalowaniem guzika mam problem, w tym kodzie z codeproject widziałem koleś malował wszystko, najechanie kursorem itd...