none
Crear un parametro puntero a una funcion - LRESULT CALLBACK WindowProcedure RRS feed

  • Pregunta

  • Estimados, buen día.

    Quería hacerles una pregunta. Estoy programando con las API de Windows y necesito hacer lo siguiente. Cree una clase para administrar las ventanas de windows. Como sabrán para que una ventana de windows funcione en c++ necesito indicarle cual será la funcion que "escuche" las peticiones de Windows.

    Clase que crea ventanas:

    HWND Windows::AddWindows(HINSTANCE pInstance, LRESULT (*pWindowProcedure) ())
    {
        HWND hHwnd;
        WNDCLASS wWndClass;

        wWndClass.style = CS_HREDRAW | CS_VREDRAW;
        wWndClass.lpfnWndProc = (long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long))pWindowProcedure;
        wWndClass.cbClsExtra = 0;
        wWndClass.cbWndExtra = 0;
        wWndClass.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
        wWndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wWndClass.hIcon = LoadCursor(NULL, IDI_APPLICATION);
        wWndClass.hInstance = pInstance;
        wWndClass.lpszClassName = this->NameWindows;
        wWndClass.lpszMenuName = NULL;

        RegisterClass(&wWndClass);

        hHwnd = CreateWindow(this->NameWindows,
                             this->TitleWindows,
                             WS_OVERLAPPEDWINDOW,
                             CW_USEDEFAULT,
                             CW_USEDEFAULT,
                             320,
                             200,
                             HWND_DESKTOP,
                             NULL,
                             pInstance,
                             NULL);

        ShowWindow(hHwnd, SW_SHOWDEFAULT);

        return hHwnd;
    }

    Prototipo de la clase: HWND AddWindows(HINSTANCE pInstance, LRESULT (*pWindowProcedure) ());

    Definicion de prototipo de WindowProcedure:

    LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam);

    Funcion WinMain:

    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
        LRESULT (*PointerWindowProcedure) ();
        Windows _Win;
        MSG _Message;

        PointerWindowProcedure = WindowProcedure;

        _Win.AddWindows(hInstance, PointerWindowProcedure);

        while(GetMessage(&_Message, 0, 0, 0) == TRUE)
        {
            TranslateMessage(&_Message);
            DispatchMessage(&_Message);
        }

        return 0;
    }

    LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
    {
        return DefWindowProc(hWnd, uMessage, wParam, lParam);
    }

    Bien, cuando intento hacer esto, tengo el error: Access violation.

    Bueno, la idea es que pueda pasarle como argumento el punto de ejecución de la funcion que captura los mensajes de windows. Intente varias cosas pero no tengo exito, probe declarar el puntero a funcion como LRESULT CALLBACK (como es la definicion de retorno de WindowProcedure) pero me da error por todos lados, probe entre parentesis (LRESULT CALLBACK) pero lo mismo.

    Muchas gracias!

    Slds,

    Nof


    - Nof

    viernes, 20 de abril de 2012 13:58

Respuestas

  • Perdón, se me pasó. El winproc de la ventana principal debe enviar un WM_QUIT.

    LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
     {
         if (uMessage == WM_DESTROY) PostQuitMessage(0);
    
         return DefWindowProc(hWnd, uMessage, wParam, lParam);
     }
    
    Fijate cómo resolvés eso.

    • Marcado como respuesta Nicolás Ben viernes, 20 de abril de 2012 17:22
    viernes, 20 de abril de 2012 16:37

Todas las respuestas

  • El tipo ya está definido en el sdk: WNDPROC.

    WindowProcedure es una función de tipo WNDPROC.

    viernes, 20 de abril de 2012 14:30
  • Buena, lo probe y tengo esto ahroa:

    C:\Nof\Listas\Listas.cpp(22) : error C2440: '=' : cannot convert from 'long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long)' to 'long (__stdcall *(__cdecl *)(struct HWND__ *,unsigned int,unsigned int,long))(struct HWND__ *,unsigned int

    El error pasa en esta linea:

    //Definicion del prototipo de WindowProcedure

    LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam);

    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
        //LRESULT (*PointerWindowProcedure) (HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam);
        WNDPROC (*PointerWindowProcedure) (HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam);
        
        Windows _Win;
        MSG _Message;

        PointerWindowProcedure = WindowProcedure;

        _Win.AddWindows(hInstance, PointerWindowProcedure);

        while(GetMessage(&_Message, 0, 0, 0) == TRUE)
        {
            TranslateMessage(&_Message);
            DispatchMessage(&_Message);
        }

        return 0;
    }

    LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
    {
        return DefWindowProc(hWnd, uMessage, wParam, lParam);
    }

    Si le dejo el cast anterior (PointerWindowProcedure = (long (__cdecl *)(struct HWND__ *,unsigned int,unsigned int,long))WindowProcedure;) también me da error. Cambie el tipo de dato de retorno en las otras funciones y no tengo error, solo en esta linea. Como debería hacer el cast?

    Slds,

    Nof


    - Nof

    viernes, 20 de abril de 2012 14:37
  • No entiendo bien este superdesacople que intentas, pero, en todo caso

    WNDPROC PointerWindowProcedure = WindowProcedure

    WNDPROC es un tipo de function pointer y el nombre WindowProcedure es la dirección de una función.

    viernes, 20 de abril de 2012 15:09
  • Lo que quiero hacer es crear una clase que encapsule toda la logica de ventanas para windows para no tener que estar escribiendo tantas lineas para armar una ventana.

    Probe lo que me indicas y me da el mismo error... cambie la definición en el puntero y en la definicion del metodo que toma el puntero a la funcion...

    Muchas gracias!

    Nof


    - Nof

    viernes, 20 de abril de 2012 15:26
  • Probe crear una ventana convencionalmente y veo que la referencia de wWndClass.lpfnWndProc es la misma que la que tengo yo cuando armo la clase... Podría ser un tema de permisos? Mismo erro tengo si intento ejecutar algunas instrucciones ASM...

    Muchas gracias,

    Nicolás


    - Nof

    viernes, 20 de abril de 2012 15:29
  • Las cabeceras las crea por defecto la plantilla. El proyecto es win32 y yo reemplazo el código por el tuyo, levemente modificado,

    #include "stdafx.h"
    #include "pepe.h"
    
    LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam);
    
    class Windows
    {
    public:
    	Windows(){NameWindows = L"PEPE"; TitleWindows = L"Título";}
    	HWND AddWindows(HINSTANCE pInstance, WNDPROC pWindowProcedure);
    
    private:
    	LPTSTR NameWindows;
    	LPTSTR TitleWindows;
    };
    
    HWND Windows::AddWindows(HINSTANCE pInstance, WNDPROC pWindowProcedure)
     {
         HWND hHwnd;
         WNDCLASS wWndClass;
     
        wWndClass.style = CS_HREDRAW | CS_VREDRAW;
         wWndClass.lpfnWndProc = pWindowProcedure;
         wWndClass.cbClsExtra = 0;
         wWndClass.cbWndExtra = 0;
         wWndClass.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
         wWndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
         wWndClass.hIcon = LoadCursor(NULL, IDI_APPLICATION);
         wWndClass.hInstance = pInstance;
         wWndClass.lpszClassName = this->NameWindows; 
        wWndClass.lpszMenuName = NULL;
     
        RegisterClass(&wWndClass);
     
        hHwnd = CreateWindow(this->NameWindows,
                              this->TitleWindows, 
                             WS_OVERLAPPEDWINDOW, 
                             CW_USEDEFAULT, 
                             CW_USEDEFAULT, 
                             320, 
                             200, 
                             HWND_DESKTOP, 
                             NULL, 
                             pInstance, 
                             NULL);
     
        ShowWindow(hHwnd, SW_SHOWDEFAULT);
     
        return hHwnd;
     }
     
    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
     {
         Windows _Win;
         MSG _Message;
     
        WNDPROC PointerWindowProcedure = WindowProcedure;
     
        _Win.AddWindows(hInstance, PointerWindowProcedure);
     
        while(GetMessage(&_Message, 0, 0, 0) == TRUE)
         {
             TranslateMessage(&_Message);
             DispatchMessage(&_Message);
         }
     
        return 0;
     }
     
    LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
     {
         return DefWindowProc(hWnd, uMessage, wParam, lParam);
     }
     
    

    viernes, 20 de abril de 2012 16:29
  • Perdón, se me pasó. El winproc de la ventana principal debe enviar un WM_QUIT.

    LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
     {
         if (uMessage == WM_DESTROY) PostQuitMessage(0);
    
         return DefWindowProc(hWnd, uMessage, wParam, lParam);
     }
    
    Fijate cómo resolvés eso.

    • Marcado como respuesta Nicolás Ben viernes, 20 de abril de 2012 17:22
    viernes, 20 de abril de 2012 16:37
  • Ok, agregue lo que me dijiste, no puse como miembros privados a las variables porque las quiero publicas... y no utilice LPTSTR sino char* supongo que no cambia no?

    Bueno no me funciono, me dio el mismo error. El proyecto es un win32... sino pruebo crear un proyecto nuevo le agrego las clases...

    Gracias!

    Nof

    PD: A vos te funciona el ejemplo que pegaste?


    - Nof

    viernes, 20 de abril de 2012 17:14
  • Luis! Ahi me di cuenta  porque no funcionaba... los miembros NameWindows y TitleWindows no estaban inicializadas con nada, o sea, le enviaba a las funciones de winapi null en el nombre y el titulo por eso se iba al cuerno. Le puse nombre y titulo y funciono!!! :)

    Muchas gracias!

    Nof


    - Nof

    viernes, 20 de abril de 2012 17:22
  • Si el proyecto no compila UNICODE entonces está bien. De todas maneras el compilador se va a quejar, porque va a elegir funciones unicode y le estarás pasando un ansi (o viceversa).

    PD: sí.

    viernes, 20 de abril de 2012 17:27