Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 261
  • Last Modified:

Is it true?

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
tao_shaobin
Asked:
tao_shaobin
  • 3
  • 2
1 Solution
 
JMuCommented:
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
 
tao_shaobinAuthor Commented:
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
 
JMuCommented:
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
Restore individual SQL databases with ease

Veeam Explorer for Microsoft SQL Server delivers an easy-to-use, wizard-driven interface for restoring your databases from a backup. No expert SQL background required. Web interface provides a complete view of all available SQL databases to simplify the recovery of lost database

 
sofCommented:
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
 
JMuCommented:
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
 
tao_shaobinAuthor Commented:
Hi, JMu:

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

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now