WinAPI::Problém s parametry funkce, přijímající zprávy – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

WinAPI::Problém s parametry funkce, přijímající zprávy – C / C++ – Fórum – Programujte.comWinAPI::Problém s parametry funkce, přijímající zprávy – C / C++ – Fórum – Programujte.com

 

Huge0
Návštěvník
6. 6. 2007   #1
-
0
-

Zdravím, mám docela vážnej problém.
Dělám hru. Chci udělat jednu třídu, kde budou proměnné pro práci s oknem a tak, a pak druhou, kde budou proměnné pro herní plochu a podobně.

Všechno by mělo běhat docela příjemně a bez problémů, jen jediná, ale dost zásadní věc nedokážu překousnout. Je to přiřazení funkce obsluhující zprávy třídě okna. Koukněte na kód, vypsal jsem to nejdůležitější:

//##** Třída window_setting pro práci s oknem. **##/////////////////////////////

class window_setting{ // Tady budou pouze proměnné a funkce potřebné pro // vytvoření a správu okna.
private:
HDC hDC; // Private GDI device context.
HGLRC hRC; // Permanent rendering context.
HWND hWnd; // Window handle okna.
//...

public:
window_setting(); // Bezparametrový konstruktor.
//...
bool create_game_window(core_t& core); // Je potřeba přijímat jádro, kvůli volání core.InitGL().

// Funkce komunikující se systémem (přijímá od něj zprávy).Musí mít
// přesný typ parametrů, navrací vlastně to samé, co přijímá.
LRESULT CALLBACK receive_system_messages(
HWND hWnd, // Handle For This Window
UINT uMsg, // Message For This Window
WPARAM wParam, // Additional Message Information
LPARAM lParam); // Additional Message Information
void resize_game_window();
void kill_game_window();
};

Problém nastává ve funkci bool window_setting::create_game_window(core_t&),
v místě, kde se se pokouším přiřadit třídě okna funkci zpracovávající zprávy:


//...
WNDCLASS wc; // Windows Class Structure
wc.lpfnWndProc = (WNDPROC) this->receive_system_messages; // Funkce která pracuje se zprávani od systému.

Zpráva kompilátoru hovoří celkem jasně - nesprávný typ parametrů funkce...
argument of type 'LRESULT (window_setting::)(HWND__*, UINT, WPARAM, LPARAM)' does not match 'LRESULT (*)(HWND__*, UINT, WPARAM, LPARAM)'

Takže jsem docela v háji. Zvlášť, když bych potřeboval té funkci předávat ještě parametr na core...
Ale dělat všechny proměnné globální, to opravdu ne.

Takže můžete mi prosím někdo poradit, jak by se dal ten problém řešit? Bez toho se asi dál
nehnu:(.
Jsou v SDL lepší nástroje? Má smysl se ho učit? A uměli byste v něm případně tento problém
řešit?

Za jakoukoli radu vám budu velice vděčný.

Nahlásit jako SPAM
IP: ...–
Jura
~ Anonymní uživatel
637 příspěvků
6. 6. 2007   #2
-
0
-

Problém je v tom, jak se volají členské funkce. Mají totiž ještě jeden skrytý parametr a tím je instance dané třídy. A jak jistě sám dobře víš, obsluha zprávy má jen čtyři parametry, jenže kompilátor to v podstatě rozvine na prametrů pět. Takže jak z toho ven? Jendoduše...pokud jsi někdy slyšel o statických členkých metodách, pak jsi vyhrál. Ale abych tu zbytečněnekecal:



class window_setting{
public:
// Funkce komunikující se systémem (přijímá od něj zprávy).Musí mít
// přesný typ parametrů, navrací vlastně to samé, co přijímá.
static LRESULT CALLBACK receive_system_messages(
HWND hWnd, // Handle For This Window
UINT uMsg, // Message For This Window
WPARAM wParam, // Additional Message Information
LPARAM lParam); // Additional Message Information
//..
};

Jenže tím se do hry dostává další zásadní problém. Jak určitě víš, statické členské fce nepotřebují k volání instanci dané třídy, z toho plyne, že existují ještě před vytvořením dané instance. Takže pokud se v nich pokusíš zavolat nějaké čleské funkce bez platného objektu, může se stát naprosto cokoliv. Proto je potřeba nějak do metody receive_system_messages dostat danou instanci. Asi te napadne použít statickou proměnnou. Jenže ta se sdílí všemio instancemi třídy, tzn. tudy ceta nevede. Řešení je o něco málo komplikovanější - vytvoříš si objekt typu windows settings uvnitř kurziva]receive_system_messages.


LRESULT CALLBACK window_setting::receive_system_messages( ...)
{
windows_settings * pwindow = static_cast<windows_settings *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));

switch(uMsg)
{
case WM_CREATE:
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)((LPCREATESTRUCT)lParam)->lpCreateParams);
break;

...
}

Takže když to shrnu:


class window_setting{
public:
// Funkce komunikující se systémem (přijímá od něj zprávy).Musí mít
// přesný typ parametrů, navrací vlastně to samé, co přijímá.
static LRESULT CALLBACK receive_system_messages(
HWND hWnd, // Handle For This Window
UINT uMsg, // Message For This Window
WPARAM wParam, // Additional Message Information
LPARAM lParam); // Additional Message Information
//..
};

LRESULT CALLBACK window_setting::receive_system_messages( ...)
{
windows_settings * pwindow = static_cast<windows_settings *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));

switch(uMsg)
{
case WM_CREATE:
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)((LPCREATESTRUCT)lParam)->lpCreateParams);
break;

}
}

// a dale pri vytvareni okna pomoci CreateWindow, je potreba nastavit LPVOID lpParam na this(tedy pokud v tride windows_settings vytvaris okno)

Nahlásit jako SPAM
IP: ...–
Jura_0
Stálý člen
6. 6. 2007   #3
-
0
-

To Huge:

Co se týče SDL, tak pokud to s hrami myslíš vážně, tak bych _začínal_ právě na něm - je jednoduchý,mocný a multiplatformí. Ale samozřejmě jako ve všem, nikde se ti nepovede nic bez problémů. Ale tohle je můj, čistě subjektivní názor.

Nahlásit jako SPAM
IP: ...–
Huge0
Návštěvník
6. 6. 2007   #4
-
0
-

Díky moc, zatím tomu moc nerozumím, ale zkusím se tím nějak prokousat, případně nastudovat detaily.

Nahlásit jako SPAM
IP: ...–
Jura_0
Stálý člen
6. 6. 2007   #5
-
0
-
Nahlásit jako SPAM
IP: ...–
Huge0
Návštěvník
7. 6. 2007   #6
-
0
-

To Jura_:
Ještě jsem to celé nepřečetl, ale vypadá, že tohle by mohlo být přesně to, co potřebuju. Díky moc.

Nahlásit jako SPAM
IP: ...–
Jura
~ Anonymní uživatel
637 příspěvků
7. 6. 2007   #7
-
0
-

To Huge:
No, ono je to v zásadě to samé, co jsem zde napsal já. Jen jsem to v tu chvíli nemohl najít..

Nahlásit jako SPAM
IP: ...–
Huge0
Návštěvník
11. 6. 2007   #8
-
0
-

Vše jede super, kromě

windows_settings * pwindow = static_cast<windows_settings *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));


chyba něco ve smyslu, nelze přetypovat LONG na windows_setting*, přesný výpis tu nemám. Nicméně když jsem to přetypoval Cčkově
(windows_settings *)(GetWindowLongPtr(hWnd, GWLP_USERDATA));
tak to jelo ok. Jaký typ přetypování bych měl použít z C++?

Nahlásit jako SPAM
IP: ...–
Jura
~ Anonymní uživatel
637 příspěvků
11. 6. 2007   #9
-
0
-

To Huge:
Mno, v C++ by sem měly používat operátory reinterpret_cast, static_cast a dynamic_cast. Jde o to, že static_cast,zjisšťuje jestli se daný argument vleze do nového typu, poku ne, tak vrátí chybu už v DOBĚ kompilace. No, nicméně musí platit, že sizeof(typu) >= sizeof(argumentu). Ale vzheldem k tomu, že přetypováš vzájemně nesouvisející typy, tak použij buď klasické Céčkovské přetypování, nebo reinterpret_cast - ale ten ti nezaručí nic jako static cast, tedy že se všechny bity vejdou do cílového typu.

Nahlásit jako SPAM
IP: ...–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 18 hostů

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý