Thread: Encapsulating DlgProc

  1. #1
    Registered User Joelito's Avatar
    Join Date
    Mar 2005
    Location
    Tijuana, BC, México
    Posts
    310

    Unhappy Encapsulating DlgProc

    Main.cpp
    Code:
    #include <windows.h>
    #include "Resource.h"
    #include "utils.h"
    #include "main.h"
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
    {
    	CDlg *pDlg = new CDlg(hInstance);
    	pDlg->SetTemplate(MAKEINTRESOURCE(IDD_DIALOG1));
    	if (!pDlg->AllocDlg())
    	{
    		MessageBox(0, "No dlg", "Error", 16);
    	}
    	pDlg->FreeDlg();
    	delete pDlg;
    	return 0;
    }
    main.h
    Code:
    class CDlg
    {
    public:
    	CDlg(HINSTANCE hInstance) : g_hInstance(hInstance){}
    	~CDlg()
    	{
    		delete[] pTemplate;
    	}
    	void SetTemplate(const char *lpTemplate)
    	{
    		int iSize = _lstrlen(lpTemplate);
    		pTemplate = new char[iSize+1];
    		_lstrcpy(pTemplate, lpTemplate);
    	}
    	bool AllocDlg()
    	{
    		hDlg = CreateDialog(g_hInstance, pTemplate, 0, DLGPROC(DlgProc));
    		return (hDlg ? true : false);
    	}
    	void FreeDlg()
    	{
    		if (hDlg) DestroyWindow(hDlg);
    	}
    	static LRESULT CALLBACK DlgProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
    	{
    		MessageBox(NULL, NULL, "Call 1", 0);
    		CDlg *Obj = reinterpret_cast<CDlg*>(GetWindowLong(hwnd, GWL_USERDATA));
    		if (Obj)
    		{
    			switch(Msg)
    			{
    			case WM_INITDIALOG:
    				{
    					SetWindowLong(hwnd, GWL_USERDATA, (LONG)Obj);
    					return Obj->DlgProc(hwnd, Msg, wParam, lParam);
    				}
    			case WM_CLOSE:
    				{
    					DestroyWindow(hwnd);
    					return Obj->DlgProc(hwnd, Msg, wParam, lParam);
    				}
    			case WM_DESTROY:
    				{
    					PostQuitMessage(0);
    					return Obj->DlgProc(hwnd, Msg, wParam, lParam);
    				}
    			}
    			return Obj->DlgProc(hwnd, Msg, wParam, lParam);
    		}
    		else
    		{
    			return Obj->DlgProc(hwnd, Msg, wParam, lParam);
    		}
    	}
    protected:
    private:
    	HINSTANCE g_hInstance;
    	char *pTemplate;
    	HWND hDlg;
    };
    My executable crashes...any ideas?
    * PC: Intel Core 2 DUO E6550 @ 2.33 GHz with 2 GB RAM: Archlinux-i686 with xfce4.
    * Laptop: Intel Core 2 DUO T6600 @ 2.20 GHz with 4 GB RAM: Archlinux-x86-64 with xfce4.

  2. #2
    Registered User Tonto's Avatar
    Join Date
    Jun 2005
    Location
    New York
    Posts
    1,465
    You return Obj->DlgProc(..) regardless of whether it's valid or not?

  3. #3
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    Code:
    CDlg *Obj = reinterpret_cast<CDlg*>(GetWindowLong(hwnd, GWL_USERDATA));
    if (Obj)
    {
    //...
    }
    else
    {
      return Obj->DlgProc(hwnd, Msg, wParam, lParam);
    }
    So if Obj is null, you try to use it? What you are trying to do simply doesn't make sense. I assume you want to associate an instance of the CDlg class with the hwnd of the dialog.

    You should either pass a pointer to a CDlg object as the lParam of the WM_INITDIALOG message (probably using the CreateDialogParam function instead of the CreateDialog macro) or you can create a CDlg object locally in your Dialog procedure. I actually prefer to use a std::map (untested since I don't have access to a compiler atm):
    Code:
    static LRESULT CALLBACK DlgProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
    {
      static std::map<HWND,CDlg> hDlg;
      switch (msg)
      {
        case WM_INITDIALOG:
          hDlg[hwnd] = new CDlg;//also free this before the window is destroyed
        break;
      }
    }
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  4. #4
    Registered User Joelito's Avatar
    Join Date
    Mar 2005
    Location
    Tijuana, BC, México
    Posts
    310
    Hi JaWiB

    Maybe you can help...
    If I'm change to CreateDialogParam, how can I fix the DlgProc?
    Thanks
    * PC: Intel Core 2 DUO E6550 @ 2.33 GHz with 2 GB RAM: Archlinux-i686 with xfce4.
    * Laptop: Intel Core 2 DUO T6600 @ 2.20 GHz with 4 GB RAM: Archlinux-x86-64 with xfce4.

  5. #5
    carry on JaWiB's Avatar
    Join Date
    Feb 2003
    Location
    Seattle, WA
    Posts
    1,972
    You would replace CreateDialog with this:
    Code:
    hDlg = CreateDialogParam(g_hInstance, pTemplate, 0,DLGPROC(DlgProc),reinterpret_cast<LPARAM>(this));
    Then you have to fix your DlgProc:
    Code:
    if (Obj)
    {
    //...
    }
    else if (Msg==WM_INITDIALOG)
    {
      SetWindowLong(hwnd,GWL_USERDATA,static_cast<LONG>(lParam));
    }
    And take a look at these lines:
    Code:
    return Obj->DlgProc(hwnd, Msg, wParam, lParam);
    You're calling DlgProc recursively (it won't ever return).
    "Think not but that I know these things; or think
    I know them not: not therefore am I short
    Of knowing what I ought."
    -John Milton, Paradise Regained (1671)

    "Work hard and it might happen."
    -XSquared

  6. #6
    Registered User Joelito's Avatar
    Join Date
    Mar 2005
    Location
    Tijuana, BC, México
    Posts
    310
    Ok, thanks..

    and thanks everyone for helping me seeing that error... lol
    * PC: Intel Core 2 DUO E6550 @ 2.33 GHz with 2 GB RAM: Archlinux-i686 with xfce4.
    * Laptop: Intel Core 2 DUO T6600 @ 2.20 GHz with 4 GB RAM: Archlinux-x86-64 with xfce4.

  7. #7
    Registered User Joelito's Avatar
    Join Date
    Mar 2005
    Location
    Tijuana, BC, México
    Posts
    310

    Talking

    Ok, this compiles correctly, but..always returns "Obj is invalid"
    Code:
    static LRESULT CALLBACK DlgProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
    	{
    		CDlg *Obj = NULL;
    		switch(Msg)
    		{
    		case WM_INITDIALOG:
    			{
    				Obj = reinterpret_cast<CDlg*>(GetWindowLong(hwnd, GWL_USERDATA));
    				break;
    			}
    		case WM_COMMAND:
    			{
    				switch(LOWORD(wParam))
    				{
    				case IDC_BUTTON1:
    					{
    						if (Obj)
    						{
    							char *p;
    							int iSize = GetWindowTextLength(Obj->GetCtrlHandle(IDC_EDIT1));
    							p = new char[iSize+1];
    							GetWindowText(Obj->GetCtrlHandle(IDC_EDIT1), p, iSize+1);
    							MessageBox(hwnd, p, "Mensaje", 64);
    							delete[] p;
    						}
    						else
    						{
    							// Error Handler
    							MessageBox(hwnd, "Obj is invalid", "Beep", 16);
    						}
    						break;
    					}
    				}
    				break;
    			}
    		case WM_CLOSE:
    			{
    				delete[] Obj;
    				DestroyWindow(hwnd);
    				break;
    			}
    		case WM_DESTROY:
    			{
    				PostQuitMessage(0);
    				break;
    			}
    		}
    		return 0;
    	}
    	bool AllocDlg()
    	{
    		hDlg = CreateDialog(g_hInstance, MAKEINTRESOURCE(id), 0, DLGPROC(DlgProc));
    		SetWindowLong(hDlg, GWL_USERDATA, reinterpret_cast<LONG>(this));
    		return (hDlg ? true : false);
    	}
    /Edit: Never mind... I solved it
    Last edited by Joelito; 03-31-2006 at 08:11 PM.
    * PC: Intel Core 2 DUO E6550 @ 2.33 GHz with 2 GB RAM: Archlinux-i686 with xfce4.
    * Laptop: Intel Core 2 DUO T6600 @ 2.20 GHz with 4 GB RAM: Archlinux-x86-64 with xfce4.

  8. #8
    Registered User Joelito's Avatar
    Join Date
    Mar 2005
    Location
    Tijuana, BC, México
    Posts
    310
    Ok, I have a final question here:
    Code:
    static LRESULT CALLBACK DlgProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
    	{
    		CDlg *Obj = reinterpret_cast<CDlg*>(GetWindowLong(hwnd, GWL_USERDATA));
    		switch(Msg)
    		{
    		case WM_INITDIALOG:
    			{
    				if (!IfFileExists("C:\\joel\\dev\\Projectos\\ini_1\\ini.ini"))
    				{
    					MessageBox(hwnd, "No ini found", "Beep", 16);
    				}
    				else
    				{
    					char *s = new char[28];
    					ReadINIStr("C:\\joel\\dev\\Projectos\\ini_1\\ini.ini", "info", "msg", s);
    					Obj->SetCtrlText(s, IDC_EDIT1); // Crash :(
    					delete[] s;
    				}
    				break;
    			}
    // so on..
    Why Obj is not valid on WM_INITDIALOG and after that works propertly? Is it possible to change this?

    Thanks
    * PC: Intel Core 2 DUO E6550 @ 2.33 GHz with 2 GB RAM: Archlinux-i686 with xfce4.
    * Laptop: Intel Core 2 DUO T6600 @ 2.20 GHz with 4 GB RAM: Archlinux-x86-64 with xfce4.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Encapsulating cmd.exe
    By bennyandthejets in forum Windows Programming
    Replies: 4
    Last Post: 05-17-2005, 12:46 AM