Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема с указателем ни функцию-член, или как ее привести в вид void* 
V
    Опции темы
Ant
Дата 5.8.2008, 11:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 47
Регистрация: 3.9.2006

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



Собственно есть код заполнения структуры класса окна:

Код

    _WNDCLASSA wc;
    wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hCursor = LoadCursorA(0, IDC_ARROW);
    wc.hIcon = LoadIconA(0, IDI_APPLICATION);
    wc.hInstance = hInstance;
    wc.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
    wc.lpfnWndProc = &CGLWindow::WinProc;
    wc.lpszClassName = "cGlWindow";
    wc.lpszMenuName = 0;
    CGLWindow::hInst = hInstance;
    RegisterClassA(&wc);


Что делать, если функция WinProc является членом класса Х? Как указатель на нее привести в необходимую форму?
PM MAIL   Вверх
Daevaorn
Дата 5.8.2008, 11:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

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



Цитата(Ant @  5.8.2008,  12:08 Найти цитируемый пост)
Как указатель на нее привести в необходимую форму? 

Если метод не статический, то он не будет работать как си-шный хендлер. Как это обойти в случае с WinAPI- воспользуйтесь поиском.
PM MAIL WWW   Вверх
Ant
Дата 5.8.2008, 13:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 47
Регистрация: 3.9.2006

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



Все перерыл. Нигде не нашел однозначного ответа smile 
PM MAIL   Вверх
Daevaorn
Дата 5.8.2008, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

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



PM MAIL WWW   Вверх
Ant
Дата 6.8.2008, 10:01 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 47
Регистрация: 3.9.2006

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



Вобщем, как я вышел из ситуации. Покурив ссылку Daevaornа (спасибо вам огромное за подсказку) решил сделать две функции, одна статическая (WndProc), в нее, при помощи CreateWindowExA передавался указатель на объект. А из нее и вызывается обычный метод класса обработки сообщений. Вообще, тема закрыта, но если у кого есть идеи или конструктивная критика готов выслушать  smile  

Код

LRESULT CALLBACK CGLWindow::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
    CGLWindow *win = 0;

    win = reinterpret_cast<CGLWindow *>(lParam);
    return win->MessageProc(hWnd, msg, wParam, lParam);
}

LRESULT CGLWindow::MessageProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
    int i;
    switch (msg){
        case WM_CREATE:{
            
            }
            break;}

        case WM_TIMER:{
            
            break;}

        case WM_SIZE:{
         
            break;}

        case WM_CLOSE:{
            PostQuitMessage(0);
            break;}

        case WM_KEYDOWN:{
            if (wParam == VK_ESCAPE) PostQuitMessage(0);
            return 0;}
        }
    return DefWindowProcA(hWnd, msg, wParam, lParam);}



Это сообщение отредактировал(а) Ant - 6.8.2008, 10:08
PM MAIL   Вверх
vaddsm
Дата 7.8.2008, 03:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

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



А это как это так? lParam служебный параметр процедуры оконных сообщений, содержит данные в зависимости от типа msg. Откуда уверенность в том, что он всегда будет хранить указатель на твой объект. При сабклассе окна на лету обычно подобный указатель запихивают в GWL_USERDATA. 

Можно пожалуйста, поподробнее описать как ты указатель на экземпляр CGLWindow передаешь.

PM MAIL   Вверх
Supersedes
Дата 7.8.2008, 07:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 36
Регистрация: 29.7.2008

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



Код

LRESULT CALLBACK CGLWindow::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
    CGLWindow *win = 0;

    win = reinterpret_cast<CGLWindow *>(lParam);
    return win->MessageProc(hWnd, msg, wParam, lParam);
}


да, я считаю что в этом месте можно сделать лучше... только не совсем понимаю чего ты хочешь добиться..
PM MAIL ICQ   Вверх
Ant
Дата 7.8.2008, 07:25 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 47
Регистрация: 3.9.2006

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



Пожалуйста. Вот конструктор класса CGLWindow:

Код

CGLWindow::CGLWindow(LPSTR strGlWindow, int Width, int Heigth,DWORD Style, bool FullScreen, HINSTANCE hInstance, CGLWindow *window){
     int i;
    _WNDCLASSA wc;
    wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hCursor = LoadCursorA(0, IDC_ARROW);
    wc.hIcon = LoadIconA(0, IDI_APPLICATION);
    wc.hInstance = hInstance;
    wc.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
    wc.lpfnWndProc = &CGLWindow::WndProc;
    wc.lpszClassName = "cGlWindow";
    wc.lpszMenuName = 0;
    CGLWindow::hInst = hInstance;
    RegisterClassA(&wc);

    for (i = 0; i < 200; i++) BaseMess[i] = ZERO;
    index = 0;

    if (!FullScreen) CGLWindow::hWnd = CreateWindowExA(0, "cGlWindow", strGlWindow, Style, 0, 0, Width, Heigth, 0, 0, hInstance, window);
    else  {
        Style = WS_POPUP;
        ShowCursor(false);
        CGLWindow::hWnd = CreateWindowA("cGlWindow", strGlWindow, Style, 0, 0, Width, Heigth, 0, 0, hInstance, 0);
        int ScreenX, ScreenY;
        Width = ScreenX = GetSystemMetrics(SM_CXSCREEN);
        Heigth = ScreenY = GetSystemMetrics(SM_CYSCREEN);
        DEVMODE dm;
        ZeroMemory(&dm, sizeof(DEVMODE));
        dm.dmSize = sizeof(DEVMODE);
        dm.dmPelsWidth = ScreenX;
        dm.dmPelsHeight = ScreenY;
        dm.dmBitsPerPel = 32;
        dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
        if (DISP_CHANGE_SUCCESSFUL != (ChangeDisplaySettings(&dm, CDS_FULLSCREEN))){
            MessageBoxA(CGLWindow::hWnd, "Ошибка перехода в полноэкранный режим", "Ошибка", MB_OK);
            ExitProcess(0);}
    }
    ShowWindow(CGLWindow::hWnd, SW_SHOW);
    UpdateWindow(CGLWindow::hWnd);
    SetFocus(CGLWindow::hWnd);
    InitializeOpenGL(Width, Heigth);
}


Согласно "Саймон Р. Windows 2000 API" Описание функции WindowsCreateEx:

Код

HWND WndowCreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowsName, 
                                       DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hwndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpvParam);


собственно, нас интересует только последний параметр. И вот что говорит г-н Саймон:
"lpvParam: LPVOID указатель на данные, которые должны быть переданы в качестве параметра lParam сообщения WM_CREATE."

Вот немного пофиксеная функция WndProc:

Код

LRESULT CALLBACK CGLWindow::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
    if (msg == WM_CREATE) win = reinterpret_cast<CGLWindow *>(lParam);

    return win->MessageProc(hWnd, msg, wParam, lParam);
}


Указатель на объект win сделал глобальным. Вчера обнаружил эту неточность и пофиксил. Хотя, как не странно, работало все и тогда.

Добавлено @ 07:27
Supersedes, Я хочу, чтобы функция обработки сообщений была членом класса CGLWindow. Это пока единственный способ, который я смог обнаружить. Проблема в том, что указатель на не статический член класса не передать в структуру класса окна, во всяком случае я не смог.

Это сообщение отредактировал(а) Ant - 7.8.2008, 07:41
PM MAIL   Вверх
vaddsm
Дата 7.8.2008, 08:17 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 128
Регистрация: 30.6.2007

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



Ага, и все же я думаю разница между этим:

Код

LRESULT CALLBACK CGLWindow::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
    CGLWindow *win = 0;

    win = reinterpret_cast<CGLWindow *>(lParam);
    return win->MessageProc(hWnd, msg, wParam, lParam);
}


и этим:

Код

LRESULT CALLBACK CGLWindow::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
    if (msg == WM_CREATE) win = reinterpret_cast<CGLWindow *>(lParam);

    return win->MessageProc(hWnd, msg, wParam, lParam);

}



весьма серьезная.

Про то с каким грохотом и почему будет вылетать программа в первом случае я писать не буду ибо ты и сам уже разобрался введя проверку    if (msg == WM_CREATE) и сделав win глобальной. Однако у такого приема  сабклассирования есть один и очень серьезный недостаток. Если ты создашь еще один экземпляр подобного класса, то во время вызова CreateWindowEx  глобальная переменная win примет значения адреса вновь созданного экземпляра класса, при этом прочие окна, созданные до, будут работать уже с ним, а не адресом экземпляра их породившим. 

Иными словами здесь надо использовать другой механизм, однозначно привязывающий к окну адрес экземпляра класса его породившего. 



PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

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


 




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


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

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