Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> GetWindowLong(), Как добраться до экземпляра класса? 
:(
    Опции темы
Royan
Дата 28.3.2004, 23:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: нет
Всего: 15



Такой вопрос:


У меня есть класс, вот его конструктор:
Код
CMyWin::CMyWin(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
...

 //Fill Message Map
 MsgMap[WM_CREATE]=&CMyWin::OnMyCreate;
 MsgMap[WM_PAINT]=&CMyWin::OnMyPaint;
 MsgMap[WM_DESTROY]=&CMyWin::OnMyDestroy;

 //Creating main window
 DoMainCreate(WS_EX_WINDOWEDGE, WS_OVERLAPPEDWINDOW, CS_VREDRAW , 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, (void *)this);
}


При создании окна один из его методов становиться продедурой обработки сообщений окна, а именно:
Код
LRESULT CALLBACK CMyWin::MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
 CMyWin* CpWnd=(CMyWin*)(GetWindowLong(hWnd, 0));
 (CpWnd->*(CpWnd->MsgMap[uMsg]))(wParam, lParam);    
...    

Понятное дело CMyWin::MainWndProc является статическим членом этого класса, и мне приходится выдирать экземпляр класса с помощью GetWindowLong, но вот беда я заполняю карту сообщений еще в конструкторе и точно знаю количество (длину) карты, но когда я получаю экземпляр моего класса через GetWindowLong, длина карты равна нулю! Я уже кучу вариантов перепробовал для второго параметра GetWindowLong но к сожалению все безрезультатно, может кто-нибудь в курсе как возвратить экземпляр класса? Может для этого нужно как-то хитро воспользоваться SetWindowLong?


--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
mr.DUDA
Дата 29.3.2004, 10:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 25
Всего: 232



Что означает последний параметр функции DoMainCreate ? Нужно после создания окна вызвать SetWindowLong(hWnd, GWL_USERDATA, (LONG)this), а в MainWndProc проверять GWL_USERDATA с пом. GetWindowLong. Начальное значение этой константы - ноль, поэтому нужно подумать, не придут ли в оконную процедуру какие-то сообщения до вызова SetWindowLong wink.gif ...


--------------------
user posted image
PM MAIL WWW   Вверх
Royan
Дата 30.3.2004, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: нет
Всего: 15



Последний параметр в DoMainCreate это lParam, из него я все-таки научился вытаскивать экземпляр класса вот как я это делаю:
Код
LRESULT CALLBACK CMyWin::InitWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
 if(uMsg==WM_NCCREATE){    
   ::SetWindowLong(hWnd, GWL_USERDATA, (long)((LPCREATESTRUCT(lParam))->lpCreateParams));
   ::SetWindowLong(hWnd, GWL_WNDPROC, (long)CMyWin::MainWndProc);
 }  
 return( DefWindowProc( hWnd, uMsg, wParam, lParam ));
}

LRESULT CALLBACK CMyWin::MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){  
 CMyWin* CpWnd=(CMyWin*)(GetWindowLong(hWnd, GWLP_USERDATA));
 try{
   CpWnd->cIter=CpWnd->MsgMap.find(uMsg);
   (CpWnd->*((CpWnd->cIter->second)))(wParam, lParam);
 }catch(...){
   return( DefWindowProc( hWnd, uMsg, wParam, lParam ));
 }  
 return NULL;
}



где архитектура CMyWin выглядит следующим образом:

Код
class CMyWin{
public:  
 CMyWin(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
 ~CMyWin();
private:
 
 static LRESULT CALLBACK InitWndProc(HWND, UINT, WPARAM, LPARAM);
 static LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
 ....
 

virtual BOOL DoMainCreate(DWORD dwExStyle, DWORD dwStyle, DWORD dwClsStyle,
 int left, int top, int width, int height,
 HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam);

 
 ....

 //System varaibles
 HINSTANCE hInst;
 HINSTANCE hPrevInst;
 LPSTR     lpCmdLine;
 int       nCmdShow;

 WNDCLASSEX wcx;  
 CREATESTRUCT cs;


 //Methods
public:
 virtual int OnMyCreate(WPARAM wParam, LPARAM lParam);
 virtual int OnMyPaint(WPARAM wParam, LPARAM lParam);
 virtual int OnMyDestroy(WPARAM wParam, LPARAM lParam);


 typedef int (CMyWin::*MsgHandler)(WPARAM,LPARAM);
 std::map<int, MsgHandler> MsgMap;
 std::map<int, MsgHandler>::iterator cIter;


public:
 HWND      hWnd;
 
};




InitWndProc нужна только для того, чтобы сохранить адрес моего класса создавшего текущее окно, и переприсвоить адрес адрес процедуры обработки сообщений.
MainWndProc должна обрабатывать сообщения.

Вроде бы в таком раскладе все должно работать но по какой-то адской причине после отрабатывания OnMyPaint, карта обнуляется! То есть OnMyCreate, вызывается и отрабатывает без каких либо упреков а здесь такая вот беда. Я пробовал сделать карту константой, но тогда как ее проинициализировать?

Это сообщение отредактировал(а) Royan - 30.3.2004, 13:30


--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
mr.DUDA
Дата 30.3.2004, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 25
Всего: 232



Цитата
Вроде бы в таком раскладе все должно работать но по какой-то адской причине после отрабатывания OnMyPaint, карта обнуляется! То есть OnMyCreate, вызывается и отрабатывает без каких либо упреков а здесь такая вот беда. Я пробовал сделать карту константой, но тогда как ее проинициализировать?

Это можно объяснить только тем, что где-то повторно вызывается InitWndProc с нулём в lParam, и обнуляется не карта, а LONG-константа, ассоциированная с окном. ИМХО, стоит поставить брякпоинт на OnMyPaint, и когда дебаггер остановится - вставить брякпоинт на InitWndProc...

З.Ы. только что подумал, а может деструктор CMyWin вызывается где-то, где не надо ? Тогда понятно, почему карта обнуляется.


--------------------
user posted image
PM MAIL WWW   Вверх
Royan
Дата 30.3.2004, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: нет
Всего: 15



Нет не помогло. Поставил brakepoint на строку
Код
::SetWindowLong(hWnd, GWL_USERDATA, (long)((LPCREATESTRUCT(lParam))->lpCreateParams));
и размер карты равен нулю. При всем при этом hWnd сохраняет свой адрес на равне со всеми осталными членами класса. У меня ведь SetWindowLong() вызывается только в WM_NCCREATE, посему вряд ли окно после WM_PAINT вдруг послало бы WM_NCCREATE, да и кто так лихо подменит процедуру обработки? Я забыл уточнуть одну деталь. В отладчике видно, что изменение происходит где-то после выхода из OnMyPaint и перед входом в MainWndProc.

Тут на лицо изменения только карты... а ее вобще возможно сделать константой?


--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
mr.DUDA
Дата 30.3.2004, 15:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 25
Всего: 232



1) исходный код OnMyPaint - в студию!
2) насчёт непредвиденного вызова деструктора - попробуй поставить на него брякпоинт


--------------------
user posted image
PM MAIL WWW   Вверх
srd
Дата 30.3.2004, 16:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нереварин
**


Профиль
Группа: Участник Клуба
Сообщений: 951
Регистрация: 30.8.2003
Где: Владивосток

Репутация: 27
Всего: 49



Извиняюсь, что влез не по теме, но хочу заметить, что lpCreateParams структуры CREATESTRUCT для MDI окон должен хранить указатель на структуру MDICREATESTRUCT. Поэтому такой способ передачи указателя на объект в оконную функцию не подходит. Может, имеет смысл всегда передавать для всех окон в lpCreateParams MDICREATESTRUCT, а сам указатель на объект записывать в член lParam этой структуры?


--------------------
Не смей читать мою подпись!!!
PM MAIL Jabber   Вверх
Royan
Дата 30.3.2004, 20:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: нет
Всего: 15



OnMyPaint выглядит так:
Код
int CMyWin::OnMyPaint(WPARAM wParam, LPARAM lParam){
 PAINTSTRUCT ps;
 HDC hdc;
 RECT rct;
 hdc = BeginPaint (this->hWnd, &ps);

 SelectObject(hdc, GetStockObject(DC_BRUSH));
 SetDCBrushColor(hdc,RGB(133, 168, 231));
 GetClientRect(hWnd, &rct);
 Rectangle(hdc, rct.left, rct.top, rct.right, rct.bottom);
 SetDCBrushColor(hdc, RGB(229, 156, 0));
 RoundRect(hdc, rct.left+20, rct.top+20, rct.right-20, rct.bottom-20, 30, 30);

 EndPaint (this->hWnd, &ps);
 return 1;
}

Ничего преступного, повоторюсь, что после return 1; карта еще существует

Я могу в принципе весь проект на мыло послать ;)

2 srd, как-то хитро получается smile.gif но я попробую...


--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
mr.DUDA
Дата 30.3.2004, 22:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


3D-маньяк
****


Профиль
Группа: Экс. модератор
Сообщений: 8244
Регистрация: 27.7.2003
Где: город-герой Минск

Репутация: 25
Всего: 232



Цитата
Ничего преступного, повоторюсь, что после return 1; карта еще существует

Я могу в принципе весь проект на мыло послать ;)

Пошли на mr_duda|@|tut.by, интересно посмотреть, где там баг может вылезти...


--------------------
user posted image
PM MAIL WWW   Вверх
Royan
Дата 1.4.2004, 15:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Dreamer
***


Профиль
Группа: Участник Клуба
Сообщений: 1708
Регистрация: 14.9.2002
Где: Лондон

Репутация: нет
Всего: 15



Благодаря неоценимым стараниям mr.DUDA были найдены причины сего глюка. Оказалась что Объект уничтожается после блока try, в функции WinMain, вследствии чего следует создавать таковой объект динамически. Вот к чему свелось решение (остальной код оказался не подвержен изменениям):
Код
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){

//Объявления...
 CMyWin *pMainWnd;
 try{
   //Create main window
   pMainWnd = new CMyWin(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
 }catch(std::runtime_error &e){

 //  ...

 // Main message loop:
 while (GetMessage(&msg, NULL, 0, 0)) {.....}
 }

 delete pMainWnd;
 return (int)(msg.wParam);
}



--------------------
Открыта вакансия Junior Java Developer'а в нашем лондонском офисе, подробнее можно узнать здесь
PM MAIL MSN   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0513 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.