Author Topic: Win32 dialogs in ARX  (Read 11169 times)

0 Members and 1 Guest are viewing this topic.

MickD

  • Gator
  • Posts: 3287
  • (x-in)->[process]->(y-out)
Win32 dialogs in ARX
« on: February 07, 2006, 05:45:41 PM »
Here are a few snippets from a quick arx that loads a modal and modeless dialog with some simple button functions which I changed only slightly from The Forgers win32 tut's and 'shoe horned' into this dll. I just hate using MFC, it's so convoluted it's depressing. The win32 api is pretty straight forward once you get used to it and very powerful and I'd much rather work in a simple environment where I can see 'everything' that is going on.

Anyway, I'm after any comments on this code to see if it's heading in the right direction, if it is I'll do a proper explanation of what's going on and how to do this with more controls etc.

Is there anything important I'm missing that may cause undesirable effects with AutoCAD?

there is an ARX file attached at the bottom for testing (built for 2004), usual beta warning - don't use while working on important files!

the window proc's
Code: [Select]
BOOL CALLBACK modelessDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    switch(Message)
    {
        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
                case IDOK:
                    MessageBox(hwnd, "Hi!", "This is a message",
                        MB_OK | MB_ICONEXCLAMATION);
                break;
                case IDCANCEL:
                    MessageBox(hwnd, "Bye!", "This is also a message",
                        MB_OK | MB_ICONEXCLAMATION);
if(!DestroyWindow(hwnd))
MessageBox(hwnd, "Failed to destroy window!", "KaBoom!",
                        MB_OK | MB_ICONEXCLAMATION);

                break;
            }
        break;
        default:
            return FALSE;
    }
    return TRUE;
};

BOOL CALLBACK modalDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    switch(Message)
    {
        case WM_INITDIALOG:

        return TRUE;
        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
                case IDOK:
                    MessageBox(hwnd, "Hi!", "This is a message",
                        MB_OK | MB_ICONEXCLAMATION);
                break;
                case IDCANCEL:
                    EndDialog(hwnd, IDCANCEL);
                break;
            }
        break;
        default:
            return FALSE;
    }
    return TRUE;
};

the functions called by the commands DLGMDL - for modal dialog and DLGMDLS - for modeless dialog.
Code: [Select]
// ----- DCSArxProject7.dlgmdl command
// Command for modal dialog test "DLGMDL"
static void DCSArxProject7dlgmdl(void)
{
// Add your code for command DCSArxProject7.dlg1 here
HWND hwnd;
hwnd = adsw_acadMainWnd();
HWND hdlg;
int ret = DialogBox(_hdllInstance,/*our dll handle*/
            MAKEINTRESOURCE(IDD_DIALOG1), hwnd, modalDlgProc);
        if(ret == IDOK){
            MessageBox(hwnd, "Dialog Button IDOK.", "Notice",
                MB_OK | MB_ICONINFORMATION);
        }
        else if(ret == IDCANCEL){
            MessageBox(hwnd, "Dialog exited with IDCANCEL.", "Notice",
                MB_OK | MB_ICONINFORMATION);
        }
        else if(ret == -1){
            MessageBox(hwnd, "Dialog failed!", "Error",
                MB_OK | MB_ICONINFORMATION);
        }
}

// - DCSArxProject7.dlgmdls command (do not rename)
// Command for modeless dialog test "DLGMDLS"
static void DCSArxProject7dlgmdls(void)
{
// Add your code for command DCSArxProject7.dlgmdls here
HWND hwnd;
hwnd = adsw_acadMainWnd();
HWND hdlg;
//test 1
hdlg = CreateDialog(_hdllInstance, /*our dll handle*/
MAKEINTRESOURCE(IDD_DIALOG1),hwnd, modelessDlgProc);
        if(hdlg != NULL)
        {
            ShowWindow(hdlg, SW_SHOW);
        }
        else
        {
            MessageBox(hwnd, "CreateDialog returned NULL", "Warning!", 
                MB_OK | MB_ICONINFORMATION);
        }
}
« Last Edit: February 07, 2006, 05:51:22 PM by MickD »
Debugging:
Being the detective in a crime movie where you're also the murderer.

“Someone's sitting in the shade today because someone planted a tree a long time ago.”
- Warren Buffet

LE

  • Guest
Re: Win32 dialogs in ARX
« Reply #1 on: February 07, 2006, 06:02:56 PM »
Here are a few snippets from a quick arx that loads a modal and modeless dialog with some simple button functions which I changed only slightly from The Forgers win32 tut's and 'shoe horned' into this dll. I just hate using MFC, it's so convoluted it's depressing. The win32 api is pretty straight forward once you get used to it and very powerful and I'd much rather work in a simple environment where I can see 'everything' that is going on.

Anyway, I'm after any comments on this code to see if it's heading in the right direction, if it is I'll do a proper explanation of what's going on and how to do this with more controls etc.

Is there anything important I'm missing that may cause undesirable effects with AutoCAD?


Works!!  here Mick.

I also, need to understand this win32 thing.... I have done some arx commands using MFC, it might be good idea, to expose the differences.... no?

Luis.

MickD

  • Gator
  • Posts: 3287
  • (x-in)->[process]->(y-out)
Re: Win32 dialogs in ARX
« Reply #2 on: February 07, 2006, 06:10:04 PM »
Luis, what you see there is all win32, MFC just 'wraps' the win32 api functions into c++ classes that are supposedly to make programming easier (phhht!). It was developed to speed up development and make applications more OO like and easier to maintain, that's ok if you know what these 'helper' classes are doing, if not your at the library developers mercy!
 Have a look at The Forger's win32 tutorials here for a brief intro to win32 -> http://www.winprog.org/tutorial/
Debugging:
Being the detective in a crime movie where you're also the murderer.

“Someone's sitting in the shade today because someone planted a tree a long time ago.”
- Warren Buffet

LE

  • Guest
Re: Win32 dialogs in ARX
« Reply #3 on: February 07, 2006, 06:19:21 PM »
if not your at the library developers mercy!
 Have a look at The Forger's win32 tutorials here for a brief intro to win32 -> http://www.winprog.org/tutorial/

Se ve papita!!!!!!!!!!!!!.... appears to be much simpler... than MFC.... is going to be in my next task(s) to learn....

Thanks.

Chuck Gabriel

  • Guest
Re: Win32 dialogs in ARX
« Reply #4 on: February 07, 2006, 06:26:58 PM »
I have a couple of questions and a comment.

Is it necessary to call DestroyWindow() at some point to kill the modeless dialog, or will closing it via the system menu perform any required cleanup?

Does your modeless dialog keep focus like it should?  I ask because there is a message, WM_ACAD_KEEPFOCUS, that you would have to handle to make the focus work right if you were using MFC.

According to the docs, modalDlgProc must call IsDialogMessage() to support keyboard navigation and "other dialog functionality."

Chuck Gabriel

  • Guest
Re: Win32 dialogs in ARX
« Reply #5 on: February 07, 2006, 06:29:41 PM »
... that's ok if you know what these 'helper' classes are doing, if not your at the library developers mercy!

Agreed.  There's way too much macro magic going on in MFC.  You could go blind trying to figure out what's really going on behind all those macros.

MickD

  • Gator
  • Posts: 3287
  • (x-in)->[process]->(y-out)
Re: Win32 dialogs in ARX
« Reply #6 on: February 07, 2006, 06:45:39 PM »

Is it necessary to call DestroyWindow() at some point to kill the modeless dialog, or will closing it via the system menu perform any required cleanup?
I tried using EndDialog but when I unloaded the arx acad crashed! a resource thing I'm guessing. Destroy window seems to clean everything up ok.
Quote
Does your modeless dialog keep focus like it should? I ask because there is a message, WM_ACAD_KEEPFOCUS, that you would have to handle to make the focus work right if you were using MFC.

Good question! I haven't dealt with modeless dialogs much and must study a bit more and look at that WM_ message some. There is some good tut's at the catch22 site about docking windows and it explains about how to keep windows 'appearing' as they are active.
here's a link -> http://www.catch22.net/tuts/   this is a great site, heaps of clever win32 stuff ;)

Quote
According to the docs, modalDlgProc must call IsDialogMessage() to support keyboard navigation and "other dialog functionality."

I don't know about that one, is it an MFC thing? As the dialog has its own window procedure, messages get sent to the window that has current focus to handle them I would have thought (?)

Thanks Chuck, these are exactly the questions that need answering to get our win32 dialogs to play nice with acad.

Debugging:
Being the detective in a crime movie where you're also the murderer.

“Someone's sitting in the shade today because someone planted a tree a long time ago.”
- Warren Buffet

MickD

  • Gator
  • Posts: 3287
  • (x-in)->[process]->(y-out)
Re: Win32 dialogs in ARX
« Reply #7 on: February 07, 2006, 06:55:57 PM »
Ok, IsDialogMessage() will be needed sooner or later, from the win32 help
Quote
The IsDialogMessage function determines whether a message is intended for the specified dialog box and, if it is, processes the message.

BOOL IsDialogMessage(

    HWND  hDlg,   // handle of dialog box
    LPMSG  lpMsg   // address of structure with message
   );   
Parameters

hDlg

Identifies the dialog box.

lpMsg

Points to an MSG structure that contains the message to be checked.

Return Value

If the message has been processed, the return value is TRUE.
If the message has not been processed, the return value is FALSE.

Remarks

Although the IsDialogMessage function is intended for modeless dialog boxes, you can use it with any window that contains controls, enabling the windows to provide the same keyboard selection as is used in a dialog box.
When IsDialogMessage processes a message, it checks for keyboard messages and converts them into selection commands for the corresponding dialog box. For example, the TAB key, when pressed, selects the next control or group of controls, and the DOWN ARROW key, when pressed, selects the next control in a group.
Debugging:
Being the detective in a crime movie where you're also the murderer.

“Someone's sitting in the shade today because someone planted a tree a long time ago.”
- Warren Buffet

Chuck Gabriel

  • Guest
Re: Win32 dialogs in ARX
« Reply #8 on: February 07, 2006, 07:00:19 PM »
The example the docs give is this:

If the user presses the TAB key while your dialog has focus, IsDialogMessage() will translate the incoming WM_KEYDOWN, WM_KEYUP, etc messages into the appropriate messages to toggle between the controls on your dialog.


[edit]
which is exactly what you just said. :lol:
[/edit]

MickD

  • Gator
  • Posts: 3287
  • (x-in)->[process]->(y-out)
Re: Win32 dialogs in ARX
« Reply #9 on: February 07, 2006, 07:06:30 PM »
After thinking about it and reading the help on DestroyWindow(), I could probably put this function in the dll 'unload' function to do the cleaning up of the resource. This would probably help data persistency but again I haven't really used them before so some testing is in order :)
Debugging:
Being the detective in a crime movie where you're also the murderer.

“Someone's sitting in the shade today because someone planted a tree a long time ago.”
- Warren Buffet

LE

  • Guest
Re: Win32 dialogs in ARX
« Reply #10 on: February 07, 2006, 07:12:46 PM »
Here are two links once CB gave to me...

http://www.relisoft.com/win32/index.htm


Creating a Reusable Dialog Class without MFC
http://www.codeguru.com/Cpp/W-D/dislog/win32/article.php/c5073/

I will check if those links are still available....

MickD

  • Gator
  • Posts: 3287
  • (x-in)->[process]->(y-out)
Re: Win32 dialogs in ARX
« Reply #11 on: February 07, 2006, 07:29:38 PM »
That will be handy once we work out how to do this without MFC, like MFC those examples just 'wrap' the underlying api to make it more user friendly for the developer and the above problems will still exist.
The reason Autodesk would prefer you to use MFC is that MFC needs to know exactly what's going on within its application for all of its classes and resources to get along without crashing. Using win32 we are 'ducking under the radar' so to speak and we are not directly interfering with the MFC model, just catching the standard window messages in our windows and handling these to work with the arx api. As long as we don't tread on any MFC toes we should be safe.;)
Debugging:
Being the detective in a crime movie where you're also the murderer.

“Someone's sitting in the shade today because someone planted a tree a long time ago.”
- Warren Buffet

MickD

  • Gator
  • Posts: 3287
  • (x-in)->[process]->(y-out)
Re: Win32 dialogs in ARX
« Reply #12 on: February 07, 2006, 10:35:57 PM »
A little bit further along -

The modal dialog works as expected so far (although I haven't tried user interaction with acad yet!) but as Check said, with the modeless dialog the WM_ACAD_KEEPFOCUS windows message is a major hurdle at this moment.
The source so far -
Code: [Select]
#include "StdAfx.h"
#include "resource.h"

//-----------------------------------------------------------------------------
#define szRDS _RXST("DCS")

//==============================================================================
//dialog proc definitions
BOOL CALLBACK modelessDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK modalDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam);

HWND _hModelessDlg = NULL; //global handle to the modeless dialog

//end dlg proc ================================================================
//-----------------------------------------------------------------------------
//----- ObjectARX EntryPoint
class CArxProject7App : public AcRxArxApp {
public:
CArxProject7App () : AcRxArxApp () {}

virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {
AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;
// TODO: Add your initialization code here

return (retCode) ;
}

virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;
// TODO: Add your code here
//###### Destroy our modeless dialog here #######
if(!DestroyWindow(_hModelessDlg))
MessageBox(NULL, "Failed to destroy window!", "KaBoom!",
MB_OK | MB_ICONEXCLAMATION);

return (retCode) ;
}

virtual void RegisterServerComponents () {
}


// ----- DCSArxProject7.dlgmdl command
// Command for modal dialog test "DLGMDL"
static void DCSArxProject7dlgmdl(void)
{
HWND _hwnd;
_hwnd = adsw_acadMainWnd();

int ret = DialogBox(_hdllInstance,/*our dll handle*/
MAKEINTRESOURCE(IDD_DIALOG1), _hwnd, modalDlgProc);
if(ret == IDOK){
MessageBox(_hwnd, "Dialog Button IDOK.", "Notice",
MB_OK | MB_ICONINFORMATION);
}
else if(ret == -1){
MessageBox(_hwnd, "Dialog failed!", "Error",
MB_OK | MB_ICONINFORMATION);
}
}

// - DCSArxProject7.dlgmdls command (do not rename)
// Command for modeless dialog test "DLGMDLS"
static void DCSArxProject7dlgmdls(void)
{

HWND _hwnd;
_hwnd = adsw_acadMainWnd();

// Add your code for command DCSArxProject7.dlgmdls here
if(_hModelessDlg==NULL)
{
_hModelessDlg = CreateDialog(_hdllInstance, /*our dll handle*/
MAKEINTRESOURCE(IDD_DIALOG1),_hwnd, modelessDlgProc);
if(_hModelessDlg != NULL)
{
ShowWindow(_hModelessDlg, SW_SHOW);
}
else
{
MessageBox(_hwnd, "CreateDialog returned NULL", "Warning!", 
MB_OK | MB_ICONINFORMATION);
}
}
else
{
ShowWindow(_hModelessDlg, SW_SHOW);
}
}
} ;

//-----------------------------------------------------------------------------
IMPLEMENT_ARX_ENTRYPOINT(CArxProject7App)

ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject7App, DCSArxProject7, dlgmdl, dlgmdl, ACRX_CMD_MODAL, NULL)
ACED_ARXCOMMAND_ENTRY_AUTO(CArxProject7App, DCSArxProject7, dlgmdls, dlgmdls, ACRX_CMD_TRANSPARENT, NULL)

//============= Dialog window procedures =======================================
BOOL CALLBACK modelessDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
int len = 0;
int i = 0;
switch(Message)
{
case WM_ACAD_KEEPFOCUS:
do
{
MessageBox(hwnd,"acad WM called at least once!", "Test ACAD call",
MB_OK | MB_ICONEXCLAMATION);
i++;
}
while(i < 1);
SetFocus(_hModelessDlg);
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
len = GetWindowTextLength(GetDlgItem(hwnd, IDC_EDIT1));
if(len > 0)
{
int i;
char* textbuf;

textbuf = (char*)GlobalAlloc(GPTR, len + 1);
GetDlgItemText(hwnd, IDC_EDIT1, textbuf, len + 1);

MessageBox(hwnd, textbuf, "Testing Modeless", MB_OK | MB_ICONEXCLAMATION);

GlobalFree((HANDLE)textbuf);
}
else
{
MessageBox(hwnd, "Nothing in Edit box to show???", "Testing Modeless",
MB_OK | MB_ICONEXCLAMATION);
}
break;
case IDCANCEL:
//just hide it, gets destroyed on dll unload
ShowWindow(_hModelessDlg, SW_HIDE);

break;
}
break;
default:
return FALSE;
}
return TRUE;
};

BOOL CALLBACK modalDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
int len = 0;
switch(Message)
{
case WM_INITDIALOG:

return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK:
len = GetWindowTextLength(GetDlgItem(hwnd, IDC_EDIT1));
if(len > 0)
{
int i;
char* textbuf;

textbuf = (char*)GlobalAlloc(GPTR, len + 1);
GetDlgItemText(hwnd, IDC_EDIT1, textbuf, len + 1);

MessageBox(hwnd, textbuf, "Testing Modal", MB_OK | MB_ICONEXCLAMATION);

GlobalFree((HANDLE)textbuf);
len = 0;
}
else
{
MessageBox(hwnd, "Nothing in Edit box to show???", "Testing Modal",
MB_OK | MB_ICONEXCLAMATION);
}
break;
case IDCANCEL:
EndDialog(hwnd, IDCANCEL);
len = GetWindowTextLength(GetDlgItem(hwnd, IDC_EDIT1));
if(len > 0)
{
int i;
char* textbuf;

textbuf = (char*)GlobalAlloc(GPTR, len + 1);
GetDlgItemText(hwnd, IDC_EDIT1, textbuf, len + 1);

acutPrintf("You type this into the text box: %s", textbuf);

GlobalFree((HANDLE)textbuf);
len = 0;
}
break;
}
break;
default:
return FALSE;
}
return TRUE;
};

arx attached for testing
Debugging:
Being the detective in a crime movie where you're also the murderer.

“Someone's sitting in the shade today because someone planted a tree a long time ago.”
- Warren Buffet

Chuck Gabriel

  • Guest
Re: Win32 dialogs in ARX
« Reply #13 on: February 07, 2006, 10:44:13 PM »
Try just returning TRUE for the WM_ACAD_KEEPFOCUS message.

MickD

  • Gator
  • Posts: 3287
  • (x-in)->[process]->(y-out)
Re: Win32 dialogs in ARX
« Reply #14 on: February 07, 2006, 11:03:44 PM »
I had tried that but the "afx_msg LONG HelloDlg::onAcadKeepFocus(UINT, LONG)" message is a member of the MFC class which your MFC dialog would be derived from which acad calls and handles the return value. I guess you would have to catch where the message come from and return the value there else you're returning it to ....

I'm catching the message Ok, just have to handle it??
Debugging:
Being the detective in a crime movie where you're also the murderer.

“Someone's sitting in the shade today because someone planted a tree a long time ago.”
- Warren Buffet