Ahoj mam dotaz ohledne funkce LRESULT CALLBACK WndProcMain(HWND m_hwnd,UINT umsg,WPARAM wParam,LPARAM lParam)
jakto že v teto funkci nevidim vytvarene (nemam pristup) k promennym tridy ve ktere je i tato funkce?? Napriklad jak zmacknu ENTER aby se nejaka hodnota nastavila na 1??Diky za odpoved
Fórum › C / C++
Winapi
To loma : Důvod je prostý - aby jsi tuto funkci mohl mít ve třídě, musíš ji uvést jako static - tzn. že funkce nepřebírá další srytý argument, kterým je pointer this.
Řešením je si do nějaké globální struktury, třeba mapy, ukládat k příslušným HWND pointer this.
Jednoduše:
//globální proměnná
std::map<HWND, void*> okna;
//Při registraci okna
okna[hwndOkna] = this;
//a na začátku callback funkce
tvojeStrukturaOkna* okno = reinterpret_cast<tvojeStrukturaOkna*>(okna[hwndZCallbackFunkce]);
okno->data...
Zdravím,
jak už psal yaqwsx, má to co dočinění s OOP a ukazateli na funkce. Jde o to, že kompilátor do všech členských (nestatických) metod dané třídy, přidavá argument - ukazatel na danou třídu. Příklad:
class Foo
{
public:
void fooMethod(int a) {
//...
}
};
// volani
Foo f;
f.fooMethod();
A mužeš si to třeba představit tak, že kompilátor z toho uděla něco jako toto:
void Foo::fooMethod(Foo* const this) {
//...
}
//volani
Foo f;
Foo::fooMethod(&f);
A jak to souvisí s ukazateli na funkce?
Je potřeba si uvědomit, že funkce má nějakou signaturu. Pokud chceš nastavit funkci nějakému ukazateli, nesmíš porušit signaturu. A zde je kámen úrazu. Ačkoliv sám ve třídě máš funkci fooMethod a ukazetel na void (*pFunc)(), tak kompilátor potichu rozšiřil fooMethod o jeden skrytý argument.
Proto má C++ ukazatel na metody. Takže když chceš předat metodu třídy do C-like ukazatele na funkci, tak se to obchází nejčastěji přes statické metody. Nicméně zde je zase problém, že statická metoda nemůže, bez instance dané třídy, přístupovat ke členským (nestatickým) atributům dané třídy. Tudíž musíš mít nějaký mechanismus, jak dostat referenci na instanci tvé třídy do statické metody. A to lze buď jak naznačil yaqwsx, nebo pokud, když už jsi ve WinApi, tak pak je velice dobrý článek: http://www.zezula.net/cz/prog/wndproc_v_tride.html
To Jura :
tak sem to zkusil presne podle toho kodu opsat, ale jakmile zmacknu END tak program prestane pracovat a musi se ukoncit... Prosim kde je chyba??
LRESULT CALLBACK WndProc(HWND m_hwnd,UINT umsg,WPARAM wParam,LPARAM lParam)
{
CWindow * py = (CWindow *)GetWindowLong(m_hwnd, GWL_USERDATA);
switch(umsg)
{
case WM_KEYDOWN:
switch (wParam)
{
case WM_CREATE:
SetWindowLong(m_hwnd, GWL_USERDATA, (LONG)((LPCREATESTRUCT)lParam)->lpCreateParams);
break;
case VK_ESCAPE:
PostQuitMessage(0);
break;
case VK_END:
py->bbbbb = true;
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(m_hwnd,umsg,wParam,lParam);
}
To loma : zkousel jsem to aji podobnym zpusobem jako yaqwsx a program mi po KLAVESE END kde nastavuju promennou prestane pracovat, jenom kdyz ji zavolam a zmacknu END tak to jde ale jinak ne Prosim kde delam chybu
...jen tak jsem na to mrkl a WM_CREATE co vim neni podvyberem WM_KEYDOWN udalosti, to mas mit uplne mimo tu vetev na stejny urovni, takhle ti ten ukazatel nejspis zustava na NULL.
py neni NULL a probehne ti opravdu WM_CREATE vetev, tomu se mi nechce verit :D
fucking shit neboli NULL, jak sem rikal, ta WM_CREATE je dulezita tu bys vyhazovat nemel a konecne ji prozmenu zkus dat tam kam patri (o patro vys)...
...ale mozna jsem uz jenom z toho cely mimo :D
To loma : Téma se trochu rozvinulo, ale co jsem letmo prohlížel, tak si myslím, že vím kde je chyba. Zpráva WM_CREATE je zasílána hned po vytvoření okna, tzn. v době, kdy v mapě ještě není uložen HWND a mapa vrátí nulu. Pro ověření projeď kód debuggerem o ověř si, že v mapě daná hodnota ještě není.
tak sem ji asi dal tam kam patri ale tam problem neni zkousel sem to i podle yaqwsx a stejnak jak prirazuju promenne hodnotu pise to chybu(program konci)
CWindow * py = (CWindow *)GetWindowLong(m_hwnd, GWL_USERDATA);
switch(umsg)
{
case WM_CREATE:
SetWindowLong(m_hwnd, GWL_USERDATA, (LONG)((LPCREATESTRUCT)lParam)->lpCreateParams);
break;
case WM_KEYDOWN:
switch (wParam)
{
case VK_ESCAPE:
PostQuitMessage(0);
break;
case VK_END:
py->bbbbb = 5;
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(m_hwnd,umsg,wParam,lParam);
no ja vlastně ani nevim proč tam tady tato funkce je SetWindowLong(m_hwnd, GWL_USERDATA, (LONG)((LPCREATESTRUCT)lParam)->lpCreateParams); ale když si psal že to mam dělat pomoci te mapy tam tam WM_CREATE vubec nemusim používat ne ja sem z toho celkem zmatený
Z čeho jsi zmatený ? Prostě máš instanci třídy a HWND okna a musíš je nějak propojit, abys pak pro HWND zjistil tu instanci.
Takže si tu vazbu můžeš uložit třeba do té mapy...
CWindow *okno = new CWindow();
HWND hwnd = CreateWindow(....);
mapa[hwnd] = okno;
Nebo ve stylu toho, co jsi sem postnul, jako userdata okna...CWindow *okno = new CWindow();
HWND hwnd = CreateWindow(....);
SetWindowLong(hwnd, GWL_USERDATA, (LONG) okno);
S tím, že ten "tvůj" kód využívá toho, že poslední parametr CreateWindow/CreateWindowEx se oknu předá se zprávou WM_CREATE, takže to vytvoření je takhle...CWindow *okno = new CWindow();
HWND hwnd = CreateWindow(...., okno);
A ten parametr se uloží při obsluze zpráv...LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
CWindow *okno = (CWindow *) GetWindowLong(hwnd, GWL_USERDATA);
switch (message)
{
case WM_CREATE:
okno = (CWindow *) ((LPCREATESTRUCT)lParam)->lpCreateParams;
SetWindowLong(hwnd, GWL_USERDATA, (LONG) okno);
break;
...
}
Přidej příspěvek
Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku
×Vložení zdrojáku
×Vložení obrázku
×Vložení videa
Uživatelé prohlížející si toto vlákno
Podobná vlákna
WinAPI — založil QWERTY
Help :'-( (winAPI) — založil Sony
WinApi 3-díl — založil Alan
WinAPI vs WinRT — založil Porcepoque
Moderátoři diskuze