Solved

Is it true?

Posted on 2000-02-20
6
236 Views
Last Modified: 2013-12-03
Hi, In win32 programming, what is the correct way to exchange data?  Do we have to use global variables to exchange data?  Say, I have a class member function within which that I create a dialog by using CreateDialog().  Then, in the dialog procedure, I expect to accept some user inputs.  Then, how can save the user input into the data member of my class.  For example:

void MyClass::MemberFunction()
{
  .........
  CreateDialog(x, x, x, DialogProc);
  .........
}

LRESULT DialogProc(x, x, x, x)
{
  // How can I save the user inputs here into the member data of MyClass?
}

Thanks,

Robin
0
Comment
Question by:tao_shaobin
  • 3
  • 2
6 Comments
 
LVL 1

Expert Comment

by:JMu
Comment Utility
This is a problem if you don't have a "decent" class library or framework.

DialogProc is a global function. A framework hides global procedure and calls your dialog-class's dialog procedure. This procedure may be in base window-class and call hundreds of predefined virtual functions like MFC does.

I don't use MFC. I've created my own framework. It also hides global dialog/window procedure. The hidden procedure finds window object every time it gets a message and calls it's virtual procedure. I override this procedure in a dialog class. Now all dialog data is accessible without global variables.

In your case I'll have to write this:
LRESULT MyClass::DialogProc(x, x, x)
....

Note that the first parameter is missing.

I'll bet you can do this with MFC, if you use it. Just add variables to CDialog-derived class.

If you don't use MFC, you just need to do more work. But, you just have to write it once.

Is this an answer to your question?

JMu
0
 
LVL 1

Author Comment

by:tao_shaobin
Comment Utility
Hi, JMu:

Thanks for your explanations.  I am sure you understand this problem.  But, I still don't know how to solve it.  Below is what I tried before(BTW, I am not using MFC also):

class MyClass
{
  bool DlgProc( HWND, UINT, WPARAM, LPARAM );
}

MyClass::AFunction()
{
   CreateDialog(x, x, x, DlgProc);
}

MyClass::DlgProc(x, x, x, x)
{

}

The compiler gave me:
error C2440: 'type cast' : cannot convert from '' to 'int (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long)'

If you could try an example and teach me how.  I would like to increase the pts.

Thanks,

Robin
0
 
LVL 1

Expert Comment

by:JMu
Comment Utility
You get error because CreateDialog expects a global function. You can write a static DlgProc inside of the MyClass, but that doesn't solve the problem. It's just a beginning.

You need one global pointer to a dialog which you are creating. Create a dialog like this (copy-paste and modified a little bit):

EnterCriticalSection();

ASSERT( ::creatingWindow == 0 );
::creatingWindow = this;

windowHandle = ::CreateDialog(
 instanceHandle,
 templateName,
 parentWindowHandle,
 DialogProc );

ASSERT( ::creatingWindow == 0 );
::creatingWindow = 0;

LeaveCriticalSection();

In static MyClass::DlgProc you should first find an object of MyClass using hwnd. If you don't find it, then it's a first message to your window. Here is the code.

      MWindow* window;

      // find window object of handle
      if ( ! Find( windowHandle, window ) )
      {
            // handle is not in the list yet
            // this is propably because we are creating a new window

            if ( ! creatingWindow )
            {
                  // something odd happened!
                  // window is not in list and could not get new window object
                  ASSERT( false );

                  // do default processing
                  return FALSE;
            }

            window = creatingWindow;
            creatingWindow = 0;

            // this is the first message to the window

            // must attach this window handle to object
            window->AttachWindow( windowHandle );

            // remember both (handle and window object)
            // so we will find window object for the handle in next messages
            Add( windowHandle, window );
      }

      ASSERT( window );

      BOOL result = window->DialogProc( message, wParam, lParam );

      if ( message == WM_NCDESTROY )
      {
            // this is the last message to the window, so remove window from this map
            Remove( windowHandle );

            // and because window does not exists anymore, tell this to the object too
            window->AttachWindow( 0 );
      }

      return result;

I have similar routine for WindowProcedure. I hope you get the idea.

JMu
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 

Accepted Solution

by:
sof earned 50 total points
Comment Utility
The proposed solution sounds a bit complex to me (sorry ;-) - here's what I normally do: use CreateDialogParam().

i.e.,

void MyClass::MemberFunction()
{
  .........
  CreateDialogParam(x, x, x, DialogProc,(LPARAM)this);
  .........
}

LRESULT
CALLBACK
DialogProc
   ( HWND hWnd
   , UINT uMsg
   , WPARAM wParam
   , LPARAM lParam
   )
{
  switch(uMsg) {

  case WM_INITDIALOG:
    SetWindowLong(hWnd,GWL_USERDATA, (LONG)lParam);
    ...
    return TRUE; // handled
  ...
  case WM_COMMAND:
    {
       MyClass* pObj = (MyClass*)GetWindowLong(hWnd, GWL_USERDATA);

     ...

    }
 }
}

No attempt at making this robust, but hopefully you get the main idea:

 * Use CreateDialogParam() to pass a pointer to the object you wish to update in your DialogProc().
 * Handle WM_INITDIALOG in that DialogProc, storing the object
reference off of the dialog box HWND.

 * Fetch the object reference via the HWND using GetWindowLong() whenever you need to get access it from within the DialogProc (cf. WM_COMMAND above.)

Hopefully that should be enough to get you going!
0
 
LVL 1

Expert Comment

by:JMu
Comment Utility
sof and tao_shaobin,

Yes, I know that my solution is more complex than sof's.

My solution is suitable for framework. Framework should not use and framework cannot use param to pass a pointer to an object. Param is open to the user of the library.

I've used sof's solution myself.

In framework it doesn't work because Windows may send a message before you have set the user data. If you try to trap this message and convert user data to a pointer, it will point to 0-address.

tao_shaobin, please test for not null before using user data.

JMu
0
 
LVL 1

Author Comment

by:tao_shaobin
Comment Utility
Hi, JMu:

I have posted another question for you to collect credit.  Thanks.
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

For most people, the WrapPanel seems like a magic when they switch from WinForms to WPF. Most of us will think that the code that is used to write a control like that would be difficult. However, most of the work is done by the WPF engine, and the W…
Entering time in Microsoft Access can be difficult. An input mask often bothers users more than helping them and won't catch all typing errors. This article shows how to create a textbox for 24-hour time input with full validation politely catching …
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now