Solved

Is it true?

Posted on 2000-02-20
6
248 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
6 Comments
 
LVL 1

Expert Comment

by:JMu
ID: 2540334
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
ID: 2540382
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
ID: 2540496
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
PeopleSoft Has Never Been Easier

PeopleSoft Adoption Made Smooth & Simple!

On-The-Job Training Is made Intuitive & Easy With WalkMe's On-Screen Guidance Tool.  Claim Your Free WalkMe Account Now

 

Accepted Solution

by:
sof earned 50 total points
ID: 2563864
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
ID: 2565145
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
ID: 2565461
Hi, JMu:

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

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

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.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

If you have ever found yourself doing a repetitive action with the mouse and keyboard, and if you have even a little programming experience, there is a good chance that you can use a text editor to whip together a sort of macro to automate the proce…
This article surveys and compares options for encoding and decoding base64 data.  It includes source code in C++ as well as examples of how to use standard Windows API functions for these tasks. We'll look at the algorithms — how encoding and decodi…
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…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

734 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