Minulla on tässä testissä lomakkeen input-kenttiä. Miten saan niiden taustavärin samaksi kuin pääikkuna?
hwndCheck1=CreateWindow("button", "AutoCheck1", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 110, 50, 100, 20, hwnd, (HMENU) 1, hInstance, NULL); // Valintaruutu
Minulla on taustavärinä GRAY, mutta nämä pikkuikkunat jää valkoisiksi.
Samoin tämä tekstin taustaväri on valkoinen:
if ( LOWORD(wParam) == 5 && SendMessage(hwndCheck1, BM_GETCHECK, 0,0) == TRUE) SetWindowText(hwndStaticCheck1, "Check1 päällä"); // BM_GETCHECK = valintaruudun tila
Laita niiden WNDCLASS-structiin sopiva hbrBackround-väri ennen rekisteröintiä. CreateSolidBrush voi auttaa.
Näistä WS_CHIlLD ikkunoista ei ole mitään WNDCLASS-luokkaa eikä rekisteröintiä, ainoastaan "äiti-ikkunasta". Pitäisikö niille tehdä sellainen?
Tässä hiukan laajemmin tuota skriptiä:
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) // ikkunaproseduuri { static HWND hwndStaticRadio, hwndStaticCheck1, hwndStaticCheck2, hwndButtonRadio,hwndButtonCheck, hwndRadio2, hwndRadio1, hwndCheck2, hwndCheck1; // kahvat switch (iMsg) // sanomien käsittelyrakenne { case WM_CREATE: // initialisaatiosanoma CreateWindow("button", NULL, WS_CHILD|WS_VISIBLE|BS_GROUPBOX, 10, 1, 760, 410, hwnd, (HMENU) 0, hInstance, NULL); // koristelaatikko hwndCheck1=CreateWindow("button", "AutoCheck1", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 110, 50, 100, 20, hwnd, (HMENU) 1, hInstance, NULL); // Valintaruutu
Tässä on lisäksi semmoinen juttu, että tuo "koristelaatikko" tulee ihan oikean väriseksi.
Pystyykö tuossa static-hommassa määrittelemään noiden tekstiruutujen väriä?
Muuttujamäärittelyssä? No ei todellakaan. Siinä pitäisi käyttää niitä WNDCLASS-structeja ja tehdä omat ikkunaluokat. On kai myös jokin funktio, jolla Windowsin perusvärejä (siis juuri nappien ja muiden värejä) muutetaan, mutta en tiedä, auttaako se tuohon. Kai nuo jollekin WndProcille lähettävät piirtoviestin tai muuta? Kannattaa tarkkailla WndProcissa, mitä viestejä sinne tulee, ja valita niistä sopiva. Myös WinAPIn ohjeet varmasti osaavat kertoa, mitä standardikontrollit lähettävät. Jos niiden piirtotapahtumaan saa tungettua itsensä väliin, niin siinähän tuo hoituu.
Miten tuo WNDCLASS tulisi tuon koodin sekaan asetella.
WNDCLASS wc; HWND hWnd; MSG msg; // Set up WNDCLASS struct wc.style = 0; wc.lpfnWndProc = (WNDPROC) Handler; wc.cbClsExtra = 0; wc.cbWndExtra = DLGWINDOWEXTRA; wc.hInstance = hInstance; wc.hIcon = LoadIcon (NULL, IDI_WINLOGO); wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject (GRAY_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = "button"; RegisterClass(&wc);
Pitäisikö muuttaa noiden ikkunoiden nimiä? Ne on nyt kaikki "buttoneita".
Tuosta kai pitää poistaa joitakin asetuksia, koska kyseessä on "äiti-ikkunassa" kiinni oleva ikkuna, ei siitä erillinen pikku-ikkuna, jolla olisi omat näkyvät raamit
Katso mallia alkuperäisen ikkunan luonnista ja sovella siitä. WinAPIn ohjeista kyllä löytyy kuvaukset kaikista tuohon structiin kelpaavista lipuista ja CreateWindow-funktiolle annettavista parametreistä. Sieltä myös selviäisi, että "button" ei ole minkään noista nimi, vaan ikkunaluokan nimi. Mutta tuohon tyyliin, kyllä.
Tuosta sai kääntäjän hyväksymän pelkästään tällä muutoksella:
wind.cpp kirjoitti:
wc.lpfnWndProc = WndProc;
Vaikuttaa siltä, että WNDCLASS ei kuitenkaan ihan pelkästään ole siihen ratkaisu. Se peittää koko alusikkunan harmaaksi, checkboxit,radiobuttonit ja tekstit katoaa siitä tyystin. Onko siihen lisäratkaisuja?
Onko tietoa, saako tuota Dev-C++ sopivilla kirjastoilla?
Todennäköisesti tuo voisi hoitua Microsoftin MFC-lla, mutta se ei ilmeisesti sovellu Dev-Cpp:lle.
Edit: Onko mahdollista tehdä nuo checkboxit ja jne. ilman, että loisi siihen lapsi-ikkunoita?
Jotakin olet nyt tehnyt väärin. Sinulla pitäisi olla oma WNDCLASS sekä pääikkunalle että eri komponenteille, onko varmasti näin? Kyllä ne värjäykset toimivat, kun ovat ennenkin toimineet.
Mahdollisuus noihin ilman lapsi-ikkunoita on sellainen, että WM_PAINT-viestin sattuessa piirtelet haluamaasi kohtaan sopivia laatikoita ja WM_MOUSEDOWNissa tunnistat, sattuiko klikkaus siihen kohti jne.
Yksi varsin hyvä idea on jonkin valmiin kirjaston käyttäminen. Esimerkkeinä näistä mainittakoon wxWidgets ja GTK, joista ainakin ensimmäinen on kuulemma hyvin helppokäyttöinen ja ainakin porttautuva. Tällaisilla ratkaisuilla häviää näkyvistä suuri määrä koodia, johon et välttämättä kuitenkaan halua itse koskea.
Ja sen verran vielä, että WM_CREATE-tapahtumaan (tai muuallekaan WndProciin) ei kannata liiaksi laittaa asioiden luomista taikka tuhoamista, koska ohjelmalle voi aivan hyvin lähettää viestejä ulkoa käsin SendMessage-funktiolla. Mitäs sitten, kun nuo nappulaikkunat on luotu muutamaan kertaan? Silloin ei ole kenelläkään kivaa. Tietenkin tältä voi välttyä merkitsemällä apumuuttujaan, että koodi on jo suoritettu.
Tiedoston wind.cpp alussa on luotu WNDCLASSEX luokalla pääikkuna.
Tässä sen jälkeinen koodi:
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) // ikkunaproseduuri { static HWND hwndStaticRadio, hwndStaticCheck1, hwndStaticCheck2, hwndButtonRadio, hwndButtonCheck, hwndRadio2, hwndRadio1, hwndCheck1, hwndCheck2; // kahvat WNDCLASS pikku; HWND hWnd; MSG msg; // Set up WNDCLASS struct pikku.style = 0; pikku.lpfnWndProc = WndProc; pikku.cbClsExtra = 0; pikku.cbWndExtra = 1; pikku.hInstance = hInstance; pikku.hIcon = LoadIcon (NULL, IDI_WINLOGO); pikku.hCursor = LoadCursor (NULL, IDC_ARROW); pikku.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); pikku.lpszMenuName = NULL; pikku.lpszClassName = "button"; RegisterClass(&pikku); switch (iMsg) // sanomien käsittelyrakenne { case WM_CREATE: // initialisaatiosanoma CreateWindow("koristelaatikko", NULL, WS_CHILD|WS_VISIBLE|BS_GROUPBOX, 10, 1, 760, 410, hwnd, (HMENU) 0, hInstance, NULL); // koristelaatikko hwndCheck1=CreateWindow("button", "AutoCheck1", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 110, 50, 100, 20, hwnd, (HMENU) 1, hInstance, NULL); // Valintaruutu hwndCheck2=CreateWindow("button", "AutoCheck2", WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX, 110, 70, 100, 20, hwnd, (HMENU) 2, hInstance, NULL); // Valintaruutu hwndRadio1=CreateWindow("button", "AutoRadio1", WS_CHILD|WS_VISIBLE|BS_AUTORADIOBUTTON, 280, 50, 100, 20, hwnd, (HMENU) 3, hInstance, NULL); // Valintanappi SendMessage(hwndRadio1, BM_SETCHECK, 1, 0); // tehdään oletusvalinta hwndRadio2=CreateWindow("button", "AutoRadio2", WS_CHILD|WS_VISIBLE|BS_AUTORADIOBUTTON, 280, 70, 100, 20, hwnd, (HMENU) 4, hInstance, NULL); // Valintanappi hwndButtonCheck=CreateWindow("button", "Check", WS_CHILD|WS_VISIBLE, 110, 120, 100, 30, hwnd, (HMENU) 5, hInstance, NULL); // painonappi hwndButtonRadio=CreateWindow("button", "Radio", WS_CHILD|WS_VISIBLE, 280, 120, 100, 30, hwnd, (HMENU) 6, hInstance, NULL); // painonappi hwndStaticCheck1=CreateWindowEx(WS_EX_STATICEDGE, "static", "Check1 pois", WS_CHILD|WS_VISIBLE, 110, 170, 100, 20, hwnd, (HMENU) 7, hInstance, NULL); // tekstinlaatikko hwndStaticCheck2=CreateWindowEx(WS_EX_STATICEDGE, "static", "Check2 pois", WS_CHILD|WS_VISIBLE, 110, 200, 100, 20, hwnd, (HMENU) 8, hInstance, NULL); // tekstinlaatikko hwndStaticRadio=CreateWindowEx(WS_EX_STATICEDGE, "static", "Radio1 päällä", WS_CHILD|WS_VISIBLE, 280, 170, 100, 20, hwnd, (HMENU) 9, hInstance, NULL); // tekstinlaatikko return 0 ; case WM_COMMAND: // lapsi-ikkunat lähettävät WM_COMMAND sanomia switch HIWORD (wParam) // HIWORD makro purkaa wParam:sta bitit 17-32 { case BN_CLICKED: // napinpainallus aiheuttaa BN_CLICKED-tapahtuman if ( LOWORD(wParam) == 5 && SendMessage(hwndCheck1, BM_GETCHECK, 0,0) == TRUE) SetWindowText(hwndStaticCheck1, "Check1 päällä"); // BM_GETCHECK = valintaruudun tila if ( LOWORD(wParam) == 5 && SendMessage(hwndCheck1, BM_GETCHECK, 0,0) == FALSE) SetWindowText(hwndStaticCheck1, "Check1 pois "); if ( LOWORD(wParam) == 5 && SendMessage(hwndCheck2, BM_GETCHECK, 0,0) == TRUE) SetWindowText(hwndStaticCheck2, "Check2 päällä"); // BM_GETCHECK = valintaruudun tila if ( LOWORD(wParam) == 5 && SendMessage(hwndCheck2, BM_GETCHECK, 0,0) == FALSE) SetWindowText(hwndStaticCheck2, "Check2 pois"); if ( LOWORD(wParam) == 6 && SendMessage(hwndRadio1, BM_GETCHECK, 0,0) == TRUE) SetWindowText(hwndStaticRadio, "Radio1 päällä"); // BM_GETCHECK = valintanapin tila if ( LOWORD(wParam) == 6 && SendMessage(hwndRadio2, BM_GETCHECK, 0,0) == TRUE) SetWindowText(hwndStaticRadio, "Radio2 päällä "); } return 0; case WM_DESTROY: // lopetussanoman sanomakäsittelijä PostQuitMessage (0); // lopetuksen vahvistus return 0; } return DefWindowProc (hwnd, iMsg, wParam, lParam) ; // sanomien oletuskäsittely }
Latasin wxWidgets-paketin. Mietin vaan, mitkä sieltä sitten tulisi linkittää. Ja tarvitseeko muuttaa tuota?
Onko niillä kaikilla muka oma menu, vai mitä nuo menuhässäkät ovat olevinaan? Koristelaatikko-ikkunaluokkaa et ole ainakaan tuossa esitellyt.
Älä ikinä, ikinä laita WndProciin koodia, joka pitäisi suorittaa vain kerran. En tosiaan ihmettele, jos tuo koko homma räjähtää. Luulisi nyt jokaisen lapsi-ikkunankin lähettävän WM_CREATE-viestin, ja ilmankin sitä... Tuossa nyt rekisteröit ikkunaluokan uudestaan aina, kun WndProc ajetaan. Nyt siis heti paikalla siirrät ikkunaluokan rekisteröinnin ja ikkunoiden luomiset jonnekin toisaalle (vaikkapa heti pääikkunan luonnin jälkeen) ja teet kahvoista globaaleja muuttujia. Katsotaan sitten uudestaan. Kannattaa myös tarkistaa, että luokan rekisteröinti onnistuu, ja käyttää ehkä jotakin vakiomuuttujaa sen sijaan, että kirjoittaa luokan nimen aina uudestaan.
Windowsin sielunelämään kannattaa tutustua kaikessa rauhassa, jos sitä aikoo käyttää. Sinuna aloittaisin nyt siitä, että aivan uuteen, irralliseen ohjelmaan tekisin yhden ainokaisen nappulan. Mitä järkeä on kirjoittaa suuri määrä koodia, jos ei ole aavistustakaan, toimiiko se?
wxWidgets tekee tuosta kaikesta helpompaa, eikä sen kanssa tarvitse (tai edes voi) koko WinAPIa nähdäkään. Se on sitten eri asia, kelpaako se kaikkiin tarkoituksiin. Oppaita löytyy Googlella, eikä manuaalia kannata lainkaan väheksyä. Itse en ole sitä käyttänyt, joten en aivan hirveästi voi siinä auttaa.
Metabolix kirjoitti:
Onko niillä kaikilla muka oma menu, vai mitä nuo menuhässäkät ovat olevinaan? Koristelaatikko-ikkunaluokkaa et ole ainakaan tuossa esitellyt.
"Menu" on semmoinen, että siinä voi valita minkä tahansa kahdesta checkboxista tai jommankumman radiobuttonista.
Koristelaatikko on alusta saakka värjäytynyt samalla värillä kuin pääikkuna, joten sen kanssa ei ole ollut ongelmia. Jos sen taustaväri jo on harmaa ja se piirtää "kehän", se ei tarvitse säätöjä.
Mutta kaikenkaikkiaan heitit minulle aika ison pallon. Saas nähdä, saanko sitä kiinni......... :)
Aihe on jo aika vanha, joten et voi enää vastata siihen.