Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: taustaväri lapsi-ikkunaan

Sivun loppuun

pistemies [20.03.2006 12:47:59]

#

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

Metabolix [20.03.2006 18:25:29]

#

Laita niiden WNDCLASS-structiin sopiva hbrBackround-väri ennen rekisteröintiä. CreateSolidBrush voi auttaa.

pistemies [20.03.2006 18:51:10]

#

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.

pistemies [21.03.2006 13:59:59]

#

Pystyykö tuossa static-hommassa määrittelemään noiden tekstiruutujen väriä?

Metabolix [23.03.2006 17:48:16]

#

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.

pistemies [23.03.2006 23:17:27]

#

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

Metabolix [25.03.2006 11:51:15]

#

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ä.

pistemies [27.03.2006 11:37:30]

#

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?

pistemies [27.03.2006 15:41:21]

#

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?

Metabolix [27.03.2006 17:35:12]

#

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.

pistemies [27.03.2006 21:46:14]

#

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?

Metabolix [28.03.2006 18:05:13]

#

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.

pistemies [28.03.2006 19:26:14]

#

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......... :)


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta