Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Tyyppimuunnos?

Sivun loppuun

Hakoulinen [23.06.2008 23:03:29]

#

Mitä L-kirjain varsinaisesti tekee tässä tyyppimuunnoksessa (LPCWSTR)L"OpenGL"? Merkistöön jotain vaikutusta? Miten saan sen vaihtamaan muuttujan tyyliä, esim. (LPCWSTR)Ltitle?

Anthaing [24.06.2008 02:03:46]

#

L toimii vain literaalien kanssa ja tarkoittaa, että vakio on "leveä". Merkkijonovakioissa tarkoittaa, että merkin tyypiksi tulee wchar_t. Muuttujiin et voi sitä käyttää.

Metabolix [24.06.2008 08:22:22]

#

L-kirjain ei kuulu tyyppimuunnokseen, olet jäsentänyt ilmauksen väärin. Tyyppimuunnos tuossa on (LPCWSTR), osoitin C-tyyliseen (nollamerkkiin loppuvaan) wide char -tekstiin. Muunnettava asia on L"OpenGL" eli wide char -muotoinen teksti "OpenGL". Windowsissa wchar_t tarkoittaa muistaakseni UTF-16:a (joka ei tosin vastaa tyypin virallisia vaatimuksia).

Hakoulinen [24.06.2008 16:49:19]

#

Jos en laita L "väliin" niin tekstit näkyvät ihme merkeillä (japania???). Miten saan sitten muuttujan sisällön näkymään oikein?

Metabolix [24.06.2008 18:16:32]

#

Kuka tässä on mitään käskenyt pois ottaa? Tilanne on hieman vastaava kuin (int)0x1234. Ei tässäkään 0x kuulu tyyppimuunnokseen vaan on osa itse lukua, ja sen poistaminen muuttaa luvun aivan toiseksi. Samoin on oman ilmauksesi kohdalla. Yhtä lailla voidaan todeta, että (int)0xmuuttuja ei ole millään tavalla toimiva "muunnos", kuten ei omakaan vastaava merkintätapasi. Tähän yhtäläisyydet loppuvatkin.

Muunnoksen pitäisi mahdollisuuksien mukaan onnistua vaikkapa (w)sprintf-funktiolla.

wchar_t *wstr = L"Teksti";
char str[100]; // Varaa tarpeeksi tilaa!
sprintf(str, "%ls", wstr);

// Tai toiseen suuntaan:
char *str = "Teksti";
wchar_t wstr[100];
wsprintf(wstr, L"%hs", str);

Hakoulinen [24.06.2008 22:26:08]

#

Nyt meni kyl ohi kovaa ja korkealta :(

Metabolix [24.06.2008 22:52:16]

#

Jos kertoisit, mitä kohtaa et ymmärtänyt, voisi olla helpompi selittää oikeita asioita. ^^ Mutta otetaanpa nyt aivan alusta.

printf("%d != %d\n", sizeof(L"teksti"), sizeof("teksti"));
// Linuxissa esimerkiksi "28 != 7"

Kuten tästä selviää, nuo kaksi erilaista tekstiä vievät aivan eri määrän muistia ja ovat siis aivan eri tavaraa. Jatkotutkimuksia voit tehdä vaikka heksamuodossa (koodivinkki). Tällöin selviää, missä muodossa data muistissa on. Esimerkiksi omalla koneellani wchar_t vie neljä tavua merkkiä kohden, vaikka ASCII-merkit ovatkin koodeiltaan aivan normaalit.

Hakoulinen [24.06.2008 23:17:53]

#

Miksi tälläinen wchar_t on olemassa? Tai mihin sitä käytetään?

Metabolix [24.06.2008 23:24:38]

#

Standardi sanoo, että yhden wchar_t:n tulee kyetä sisältämään mikä tahansa järjestelmän tuntema merkki. Tämän takia UTF-16 ei täytä vaatimuksia: monet mutkikkaammat merkit vievät kaksi 16-bittistä lukua. Sen sijaan Linuxissa yleisesti käytettävä 32-bittinen luku riittää kattamaan koko Unicode-merkistön ja paljon ylikin. Joka tapauksessa tyypin tarkoitus on siis antaa tuki normaalia ASCII-merkistöä huomattavasti laajemmalle merkistölle. Luonnollisesti funktioistakin on tällöin usein kaksi versiota, "tavallinen" ja wide char -versio. Windowsissa jälkimmäisen tunnistaa yleensä W-kirjaimesta. Tavallisissa taitaa olla A, ja ilman näitä tunnisteita valittava funktio riippuu kääntäjän asetuksista (jotka usein tuntuvat suosivan tavallisia versioita).

Anthaing [25.06.2008 00:06:37]

#

Asian vierestä, mutta nuo funktioversiot muuten valitaan ihan esikääntäjällä. #define UNICODE ennen WinAPI-otsikkotiedostojen lisäystä valitsee W-päätteiset.

Metabolix [26.06.2008 10:29:59]

#

Anthaing kirjoitti:

Asian vierestä, mutta nuo funktioversiot muuten valitaan ihan esikääntäjällä. #define UNICODE ennen WinAPI-otsikkotiedostojen lisäystä valitsee W-päätteiset.

Toki näinkin, mutta funktioista voi käyttää myös haluamaansa vaihtoehtoa (vaikka molempia), ja ilman tuota UNICODEa valikoituu tietenkin A-päätteinen vaihtoehto. Lopputulos ilman omia säätöjä riippuu siis kehitysympäristön oletusasetuksista.

Hakoulinen [26.06.2008 20:40:37]

#

Kiitos vastauksista. Hieman vaikeaselkoinen asia vain :)

Hakoulinen [07.07.2008 20:53:30]

#

Miten saan CreateGLWindowin ensimmäisen parametrin LPCWSTR-muotoon? Kokeilin soveltaa Metabolixin koodia ylempää, mutta laihalla menestyksellä.

BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
    GLuint        PixelFormat;            // Holds The Results After Searching For A Match
    WNDCLASS    wc;                        // Windows Class Structure
    DWORD        dwExStyle;                // Window Extended Style
    DWORD        dwStyle;                // Window Style
    RECT        WindowRect;                // Grabs Rectangle Upper Left / Lower Right Values
    WindowRect.left=(long)0;            // Set Left Value To 0
    WindowRect.right=(long)width;        // Set Right Value To Requested Width
    WindowRect.top=(long)0;                // Set Top Value To 0
    WindowRect.bottom=(long)height;        // Set Bottom Value To Requested Height

    fullscreen=fullscreenflag;            // Set The Global Fullscreen Flag

    hInstance            = GetModuleHandle(NULL);                // Grab An Instance For Our Window
    wc.style            = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;    // Redraw On Size, And Own DC For Window.
    wc.lpfnWndProc        = (WNDPROC) WndProc;                    // WndProc Handles Messages
    wc.cbClsExtra        = 0;                                    // No Extra Window Data
    wc.cbWndExtra        = 0;                                    // No Extra Window Data
    wc.hInstance        = hInstance;                            // Set The Instance
    wc.hIcon            = LoadIcon(NULL, IDI_WINLOGO);            // Load The Default Icon
    wc.hCursor            = LoadCursor(NULL, IDC_ARROW);            // Load The Arrow Pointer
    wc.hbrBackground    = NULL;                                    // No Background Required For GL
    wc.lpszMenuName        = NULL;                                    // We Don't Want A Menu
    wc.lpszClassName    = (LPCWSTR)L"OpenGL";                    // Set The Class Name

    if (!RegisterClass(&wc))                                    // Attempt To Register The Window Class
    {
        MessageBox(NULL,(LPCWSTR)L"Failed To Register The Window Class.",(LPCWSTR)L"ERROR",MB_OK|MB_ICONEXCLAMATION);
        return FALSE;                                            // Return FALSE
    }

    if (fullscreen)                                                // Attempt Fullscreen Mode?
    {
        DEVMODE dmScreenSettings;                                // Device Mode
        memset(&dmScreenSettings,0,sizeof(dmScreenSettings));    // Makes Sure Memory's Cleared
        dmScreenSettings.dmSize=sizeof(dmScreenSettings);        // Size Of The Devmode Structure
        dmScreenSettings.dmPelsWidth    = width;                // Selected Screen Width
        dmScreenSettings.dmPelsHeight    = height;                // Selected Screen Height
        dmScreenSettings.dmBitsPerPel    = bits;                    // Selected Bits Per Pixel
        dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

        // Try To Set Selected Mode And Get Results.  NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
        if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
        {
            // If The Mode Fails, Offer Two Options.  Quit Or Use Windowed Mode.
            if (MessageBox(NULL,(LPCWSTR)L"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?",(LPCWSTR)L"NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
            {
                fullscreen=FALSE;        // Windowed Mode Selected.  Fullscreen = FALSE
            }
            else
            {
                // Pop Up A Message Box Letting User Know The Program Is Closing.
                MessageBox(NULL,(LPCWSTR)L"Program Will Now Close.",(LPCWSTR)L"ERROR",MB_OK|MB_ICONSTOP);
                return FALSE;                                    // Return FALSE
            }
        }
    }

    if (fullscreen)                                                // Are We Still In Fullscreen Mode?
    {
        dwExStyle=WS_EX_APPWINDOW;                                // Window Extended Style
        dwStyle=WS_POPUP;                                        // Windows Style
        ShowCursor(FALSE);                                        // Hide Mouse Pointer
    }
    else
    {
        dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;            // Window Extended Style
        dwStyle=WS_OVERLAPPEDWINDOW;                            // Windows Style
    }

    AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);        // Adjust Window To True Requested Size

    //Tähän se toiminta, joka muuttaa muuttujan title LPCWSTR-muotoon? En saanut toimimaan Metabolixin koodia soveltamalla

    // Create The Window
    if (!(hWnd=CreateWindowEx(    dwExStyle,                            // Extended Style For The Window
                                (LPCWSTR)L"OpenGL",                    // Class Name
                                title,                        // Window Title
                                dwStyle |                            // Defined Window Style
                                WS_CLIPSIBLINGS |                    // Required Window Style
                                WS_CLIPCHILDREN,                    // Required Window Style
                                0, 0,                                // Window Position
                                WindowRect.right-WindowRect.left,    // Calculate Window Width
                                WindowRect.bottom-WindowRect.top,    // Calculate Window Height
                                NULL,                                // No Parent Window
                                NULL,                                // No Menu
                                hInstance,                            // Instance
                                NULL)))                                // Dont Pass Anything To WM_CREATE

Hakoulinen [07.07.2008 20:57:38]

#

line 320 : error C2664: 'CreateWindowExW' : cannot convert parameter 3 from 'char *' to 'LPCWSTR'

Tahdon muuttaa tuon kyseisen kolmannen parametrin oikeaan muotoon :)

Metabolix [07.07.2008 21:01:49]

#

Metabolix oikeastaan kirjoitti:

const char *str = "Teksti";
const int size = (strlen(str) + 1) * sizeof(wchar_t);
wchar_t *wstr = malloc(size);
wsprintf(wstr, L"%hs", str);
/* Käyttö tässä välissä */
free(wstr);

Ei nyt ole Windowsia käsillä, joten jos tämä ei toimi, voisit vielä kertoa, miten se ei toimi, ja antaa vaikkapa linkittämäni koodivinkin mukaisen dumppauksen, dump(stdout, wstr, size);

Hakoulinen [07.07.2008 21:08:01]

#

Sovelsinkohan nyt väärin:

BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)


	const int size = (strlen(title) + 1) * sizeof(wchar_t);
	wchar_t *wstr = malloc(size);
	wsprintf(wstr, "%hs", title);

    // Create The Window
    if (!(hWnd=CreateWindowEx(    dwExStyle,                            // Extended Style For The Window
                                (LPCWSTR)L"OpenGL",                    // Class Name
                                title,                        // Window Title
                                dwStyle |                            // Defined Window Style
                                WS_CLIPSIBLINGS |                    // Required Window Style
                                WS_CLIPCHILDREN,                    // Required Window Style
                                0, 0,                                // Window Position
                                WindowRect.right-WindowRect.left,    // Calculate Window Width
                                WindowRect.bottom-WindowRect.top,    // Calculate Window Height
                                NULL,                                // No Parent Window
                                NULL,                                // No Menu
                                hInstance,                            // Instance
                                NULL)))                                // Dont Pass Anything To WM_CREATE
    {
        KillGLWindow();                                // Reset The Display
        MessageBox(NULL,(LPCWSTR)L"Window Creation Error.",(LPCWSTR)L"ERROR",MB_OK|MB_ICONEXCLAMATION);
        return FALSE;                                // Return FALSE
    }

	free(wstr);
1>c:\users\roope\documents\visual studio 2008\projects\gl\opengl\main.cpp(307) : error C2440: 'initializing' : cannot convert from 'void *' to 'wchar_t *'
1>        Conversion from 'void*' to pointer to non-'void' requires an explicit cast
1>c:\users\roope\documents\visual studio 2008\projects\gl\opengl\main.cpp(308) : error C2664: 'wsprintfW' : cannot convert parameter 2 from 'const char [4]' to 'LPCWSTR'
1>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>c:\users\roope\documents\visual studio 2008\projects\gl\opengl\main.cpp(323) : error C2664: 'CreateWindowExW' : cannot convert parameter 3 from 'char *' to 'LPCWSTR'
1>        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

Metabolix [07.07.2008 21:16:04]

#

Käytät C++:aa (et maininnut), joten kääntäjälle täytyy erikseen kertoa, että tiedät, mitä teet. Tarvitset siis malloc-funktion paluuarvolle tyyppimuunnoksen (LPCWSTR tai wchar_t*). Funktion sprintfw formaattiin täytyy nähtävästi lisätä L eteen. CreateWindowEx-kutsussa tietenkin käytetään tätä muunnettua tekstiä (wstr) vanhan (title) sijaan.

... wstr = (wchar_t *) malloc(...);
wsprintf(wstr, L"%hs", title);

Hakoulinen [07.07.2008 21:24:31]

#

Kiitos taas kerran Metabolix.. Nyt toimii.

Metabolix [07.07.2008 21:25:59]

#

Jos tässä vaikka itsekin vahingossa oppisi jotain... Jos ei muuta niin sen, että riemu on olla käyttämättä itse WinAPInaa. Suosittelen sinullekin jotain näppärämpiä rajapintoja, edes SDL:ää.

Hakoulinen [07.07.2008 21:34:35]

#

Harkitsemisen arvoinen idea.. Tämä on ensimmäinen WinAPIlla kokeilemani juttu ja vähän huono maku jäi :) Voisi kyllä yrittää koota SDL:än kautta..


Sivun alkuun

Vastaus

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

Tietoa sivustosta