Thread: Display text in a Dialog Box

  1. #1
    Darkness Prevails Dark_Phoenix's Avatar
    Join Date
    Oct 2006
    Location
    Houston, Texas
    Posts
    174

    Display text in a Dialog Box

    I want to be able to display text in a dialog box based on user input. For example, if I had a button on the main window that displayed a dialog box with customer information. This information would change based on the customer name that the user enters so I can't hard code it in the dialog resorce templete. I've used this meathod in the WndProc to display text on the main window but when I put it in the DlgProc it does not do anything, no text or errors.
    Code:
        case WM_PAINT:
        {
            RECT rect;
            HDC hdc;
            PAINTSTRUCT ps;
            if (!(hdc = BeginPaint(hWnd, &ps) ) )
                MessageBox(hWnd, "BeginPaint() failed", "error", NULL);
     
            SetTextColor(hdc, RGB(0, 0, 0) );
            SetBkColor(hdc, RGB(245, 245, 245) );
            GetClientRect(hWnd, &rect);
            if (!TextOut(hdc, 45, 45, "this is a test", 14) )
                MessageBox(hWnd, "TextOut() failed", "error", NULL);
     
            EndPaint(hWnd, &ps);
        }
        break;
    How else can I display text to a dialog box?
    Using Code::Blocks and Windows XP

    In every hero, there COULD be a villain!

  2. #2
    Registered User
    Join Date
    Dec 2007
    Posts
    214
    Are you sure the hWnd is the handle to your dialog?

    I made a sample app. It has an about dialog. I put your code into the message handler for the about box. It paints the "this is a test" text on the dialog. In my test app, the first parameter to the About message handler is HWND hDlg. I used that handle (replacing your hWnd).

  3. #3
    Darkness Prevails Dark_Phoenix's Avatar
    Join Date
    Oct 2006
    Location
    Houston, Texas
    Posts
    174
    Thats what I thought at first too... So I put in some code to check the handles...
    Code:
    inline void DisplayHandle(const char *text, HWND hWnd)
    {
        std::stringstream ss;
        std::string s;
        if (ss<<hWnd <<std::flush)
            s = ss.str();
        else
            s = "-1";
        const char *c = s.c_str();
        MessageBox(NULL, (LPCSTR)c, (LPCSTR)text, NULL);
    }
    I called DisplayHandle right after I created the dialog and at the begining of WM_PAINT in the DlgProc and they both displayed the same value.

    I know it is something simple I just can't quite put my finger on it...
    Using Code::Blocks and Windows XP

    In every hero, there COULD be a villain!

  4. #4
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    Code:
     
    #include <windows.h>
    #include <stdio.h>
     
    char pMessage[256];
     
    sprintf(pMessage , "Hello World!\n");
    MessageBox(NULL , pMessage , "User Input Display" , MB_OK);

  5. #5
    Darkness Prevails Dark_Phoenix's Avatar
    Join Date
    Oct 2006
    Location
    Houston, Texas
    Posts
    174
    Quote Originally Posted by abachler View Post
    Code:
     
    #include <windows.h>
    #include <stdio.h>
     
    char pMessage[256];
     
    sprintf(pMessage , "Hello World!\n");
    MessageBox(NULL , pMessage , "User Input Display" , MB_OK);
    I wish it was that easy (or is it?) but I want to be able to add some other controls to the dialog as well.

    So I tried something a little easier... printing some text in response to a menu selection.

    So I put this code in to my WndProc
    Code:
            case WM_COMMAND:
            {
                switch (LOWORD(wParam) )
                {
                    case IDD_CUSTOMERLOOKUP:
                    {
                        RECT TitleRect;
                        PAINTSTRUCT ps;
                        HDC hdc = BeginPaint(hWnd, &ps);
                        GetClientRect(hWnd, &TitleRect);
                        SetTextColor(hdc, RGB(0, 0, 0) );
                        SetBkColor(hdc, RGB(245, 245, 245) );
                        TextOut(hdc, 100, 100, "this is a test", 14);
                        EndPaint(hWnd, &ps);
                    }
                    break;
                }
            }
    and again... nothing. But the same bit of code works just fine if I put it with the WM_PAINT message. Do drawing operations have to be done within the WM_PAINT message?
    Using Code::Blocks and Windows XP

    In every hero, there COULD be a villain!

  6. #6
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    Just like DaveH, I also cannot recreate your problem. Is it feasible to post more of your code? For instance, post the DlgProc function code.

  7. #7
    Darkness Prevails Dark_Phoenix's Avatar
    Join Date
    Oct 2006
    Location
    Houston, Texas
    Posts
    174
    Well, looks like it may be in how I am creating my framework. I've used this method in some simpler programs that have worked fine but now it seems like it is broken somewhere...

    Basic functins are controlled by my CFramework class
    Code:
    class CFramework
    {
        public:
        CFramework(CBaseApp* pApp);
        ~CFramework() { Release(); }
        bool Initialize(char* title, HINSTANCE hInstance, CBaseApp *pApp);
        void Release();
        void AttachWndProc(HWND h, CBaseApp *pClass) { m_WndMap[h] = pClass; }
        void RemoveWndProc(HWND h) { m_WndMap.erase(h); }
        void AttachDlgProc(HWND h, CBaseDialog *pClass) { m_DlgMap[h] = pClass; }
        void RemoveDlgProc(HWND h) { m_DlgMap.erase(h); }
        int Run();
    
        BOOL MakeButton(LPCTSTR title, int x, int y, int h, int w, HWND hParent, int id, HWND *hReturn);
        BOOL MakeDialog(int type, HWND hParentWnd, CBaseDialog *pNewDialog, CBaseDialog *pOldDialog = NULL);
    
        static LRESULT CALLBACK StaticWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
        static BOOL CALLBACK StaticDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    
        static hWndMap m_WndMap;
        static hDlgMap m_DlgMap;
    
        private:
        void OnCreateControl();
        void OnDestroyControl();
    
        HWND                   m_hWnd;
        HINSTANCE              m_hInstance;
    
        CBaseApp              *m_pApp;
        CBaseDialog           *m_pDialog;
    };
    and I have a CApp class that is derived from a virtual CBaseApp class
    Code:
    class CBaseApp
    {
        public:
        virtual ~CBaseApp() { }
        virtual void Release()              = 0;
        virtual void OnCreateControl(HWND)  = 0;
        virtual void OnDestroyControl()     = 0;
        virtual int Run()                   = 0;
    };
    
    class CApp : public CBaseApp
    {
        public:
        CApp();
        ~CApp () { Release(); }
        void Release();
        void OnCreateControl(HWND hWnd);
        void OnDestroyControl();
        int Run();
        bool Initialize();
        void SetFramework(CFramework* pFramework) { m_pFramework = pFramework; }
        LRESULT CALLBACK InstanceWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    
        private:
        CFramework          *m_pFramework;
        CBaseDialog         *m_pCurrentDlg;
        CDlgTrace            m_DlgTrace;
        CDlgCustomerLookup   m_DlgCustomerLookup;
        CDlgCityDispatchPlan m_DlgCityDispatchPlan;
    };
    and a CDialog class which is derived similarly from a CBaseDialog class.
    Code:
    class CBaseDialog
    {
        public:
        virtual ~CBaseDialog() { }
        virtual void Release()                               = 0;
        virtual HWND Create(int type, HWND hParentWnd)       = 0;
        virtual HWND GetHandle()                             = 0;
        virtual BOOL CALLBACK InstanceDlgProc(HWND hwnd,
                                              UINT msg,
                                              WPARAM wParam,
                                              LPARAM lParam) = 0;
    };
    
    class CDlgCustomerLookup : public CBaseDialog
    {
        public:
        CDlgCustomerLookup() { m_hDialog = NULL; m_hParentWnd = NULL; }
        ~CDlgCustomerLookup() { Release(); }
        void Release() { if (m_hDialog != NULL) {DestroyWindow(m_hDialog);m_hDialog = NULL; } }
        HWND Create(int type, HWND hParentWnd);
        HWND GetHandle() { return m_hDialog; }
        BOOL CALLBACK InstanceDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    
        private:
        HWND       m_hDialog;
        HWND       m_hParentWnd;
    };
    and my WinMain
    Code:
    int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
    {
        CApp *pApp = new CApp();
        CFramework *pFramework = new CFramework( (CBaseApp*)pApp);
        int msg;
    
        pApp->SetFramework(pFramework);
    
        if (pApp->Initialize() )
        {
            // Initialize the Framework
            if (pFramework->Initialize("Test App", hInst, pApp) )
            {
                // Run the application
                msg = pFramework->Run();
            }
            else
                SHOWERROR("CFramework::Initialize() failed");
        }
        else
            SHOWERROR("CApp::Initialize() failed");
    
        // Clean up resources
        delete pFramework;
        delete pApp;
    
        return msg;
    }
    and the message loop starts in CFramework where I simple transfer control to CApp so I can do application dependent processing such as IsDlgMessage()
    Code:
    int CFramework::Run()
    {
        if (m_pApp != NULL)
        {
            return m_pApp->Run();
        }
        return 0;
    }
    
    int CApp::Run()
    {
        MSG Msg;
        while(GetMessage(&Msg, NULL, 0, 0) > 0)
        {
            BOOL handled = FALSE;
            if (m_pCurrentDlg)
                handled = IsDialogMessage(m_pCurrentDlg->GetHandle(), &Msg);
            if (!handled)
            {
                TranslateMessage(&Msg);
                 DispatchMessage(&Msg);
            }
        }
        return Msg.wParam;
    }
    m_pCurrentDlg is simply a pointer to a CBaseDialog object which is the current dialog box being displayed
    I am using a std::map to link the window handle with the InstanceWndProc, and the same with the dialogs, as seen in CFramework::AttachWndProc and CFramework::AttachDlgProc
    I am using a static WndProc and DlgProc to direct messages to the correct instance
    Code:
    LRESULT CALLBACK CFramework::StaticWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        hWndMap::iterator it = m_WndMap.find(hWnd);
        if (it != m_WndMap.end() )
        {
            CApp *pClass = (CApp*)it->second;
            return pClass->InstanceWndProc(hWnd, msg, wParam, lParam);
        }
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    
    BOOL CALLBACK CFramework::StaticDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        hDlgMap::iterator it = m_DlgMap.find(hDlg);
        if (it != m_DlgMap.end() )
        {
            CDialog *pClass = (CDialog*)it->second;
            return pClass->InstanceDlgProc(hDlg, msg, wParam, lParam);
        }
        return FALSE;
    }
    This part is working, as I can create controls in the InstanceWndProc based off of menu selections on the menu bar. But it seems like the correct hWnd is not being sent as it is just the functions that require a HWND are not working right. For instance, in my InstanceWndProc I have
    Code:
            // Menu Bar Commands
            case WM_COMMAND:
            {
                switch (LOWORD(wParam) )
                {
                    case IDD_CUSTOMERLOOKUP:
                    {
                        if(!m_pFramework->MakeDialog(LOWORD(wParam), hWnd, &m_DlgCustomerLookup, m_pCurrentDlg) )
                            SHOWERROR("Dialog Creation Failed");
                        m_pCurrentDlg = &m_DlgCustomerLookup;
                    }
                    break;
                }
            }
            break;
    and this creates the correct dialog box. But if I replace this with a simple TextOut() command, nothing happens.

    I know this is a bit to look through and I'm sure it is something simple but I am completely at a loss here. Thanks to anyone willing to help.
    Using Code::Blocks and Windows XP

    In every hero, there COULD be a villain!

  8. #8
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    I'd have to agree with DaveH and say that you're probably using the wrong window handle.

    One sure way of verifying this is to download the WinId freeware utility if you're NOT using Vista and independently verify the handle of the target window and compare it with the handle being used by your app. This utility is the equivalent of WinSpy++.

  9. #9
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    BeginPaint() can only be called in a WM_PAINT msg, it is not valid otherwise.


    How are you triggering the WM_PAINT msg? I can not see a call to InvalidateRect()

    I would check the rectangle in the PAINTSTRUCT returned in the call to BeginPaint() as it may be empty.
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  10. #10
    Darkness Prevails Dark_Phoenix's Avatar
    Join Date
    Oct 2006
    Location
    Houston, Texas
    Posts
    174
    Quote Originally Posted by BobS0327 View Post
    One sure way of verifying this is to download the WinId freeware utility
    Nice utility, Thanks for that

    Quote Originally Posted by novacain View Post
    How are you triggering the WM_PAINT msg? I can not see a call to InvalidateRect()
    And that was the problem, I was not calling InvalidateRect()

    Thanks for all the help guys!
    Using Code::Blocks and Windows XP

    In every hero, there COULD be a villain!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Set Printer Prior To Loading Print Dialog Box
    By Beaner in forum Windows Programming
    Replies: 3
    Last Post: 10-10-2008, 01:02 PM
  2. A bunch of Linker Errors...
    By Junior89 in forum Windows Programming
    Replies: 4
    Last Post: 01-06-2006, 02:59 PM
  3. edit box affecting displaying of text?
    By algi in forum Windows Programming
    Replies: 4
    Last Post: 05-04-2005, 03:28 PM
  4. struct question
    By caduardo21 in forum Windows Programming
    Replies: 5
    Last Post: 01-31-2005, 04:49 PM
  5. Dialog Box Resources
    By Mecnels in forum Windows Programming
    Replies: 2
    Last Post: 04-28-2003, 05:57 AM