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

0 Members and 1 Guest are viewing this topic.

MickD

  • Gator
  • Posts: 3290
  • (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: 3290
  • (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: 3290
  • (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: 3290
  • (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: 3290
  • (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: 3290
  • (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: 3290
  • (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: 3290
  • (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

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Win32 dialogs in ARX
« Reply #15 on: February 08, 2006, 12:00:04 AM »
In AC2006 :
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

MickD

  • Gator
  • Posts: 3290
  • (x-in)->[process]->(y-out)
Re: Win32 dialogs in ARX
« Reply #16 on: February 08, 2006, 12:14:54 AM »
Thanks Kerry, hadn't tried it in 2005/6, seems to work ok. :)
Although I could probably do without modeless dialogs for my personal needs, this is presenting quite a challange that is worth persuing as it will be a good learning tool for using win32 and all its power....mmwaAHAHAHa! :D
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 #17 on: February 08, 2006, 12:28:34 PM »
I see, that the samples are using the functions GlobalXXX for memory management... I remember when I wrote my ClipBoard project, that they recommended to use "Heap Functions"

Quote
Note  The global functions are slower than other memory management functions and do not provide as many features. Therefore, new applications should use the heap functions. However, the global functions are still used with DDE and the clipboard functions.

It will be [I think simple to just change] GlobalXXX to HeapXXX

If the above does not make any sense... please ignored...  :ugly:

MickD

  • Gator
  • Posts: 3290
  • (x-in)->[process]->(y-out)
Re: Win32 dialogs in ARX
« Reply #18 on: February 08, 2006, 05:48:01 PM »
Luis, it was just a copy and paste of something I knew worked to get something going, this would definitely not be production code ;)

Try just returning TRUE for the WM_ACAD_KEEPFOCUS message.

Chuck, you're right, it should work after thinking about it and looking at the mfc samples in the sdk (where they simply return TRUE). The message map simply maps your functions to windows messages anyway so there is no difference really. Must be missing something simple here...
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

cornbread

  • Guest
Re: Win32 dialogs in ARX
« Reply #19 on: February 13, 2006, 12:43:43 PM »
If you ever figure out what it is let us know. I always process the WM_ACAD_KEEPFOCUS message by returning TRUE and it seems to have no effect on my modeless dialogs. I don't work much with Acad but I do rember battling with that for a while and then giving up because I could never get it to keep the focus even following the API and processing that message. The message does get sent you can watch it in a symbol debugger but it's almost like Acad ignores it. I could never find what I was missing to make it truly modeless.

MickD

  • Gator
  • Posts: 3290
  • (x-in)->[process]->(y-out)
Re: Win32 dialogs in ARX
« Reply #20 on: February 13, 2006, 03:59:15 PM »
Yep, I've just about given up also and I was clearly catching the message too. I really thought that MFC just mapped the messages to functions to handle them (and I still do), maybe it's something to do with the MFC dialog class that you derive your dialogs from that has some magic??
Maybe it might be a case of hooking into the main window proc and catching/handling it somehow?
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

cornbread

  • Guest
Re: Win32 dialogs in ARX
« Reply #21 on: February 14, 2006, 01:21:34 PM »
Cr@p in thinking about it I figured out what was wrong. Set the style of the dialog to overlapped either via a WS_OVERLAPPED if you are doing it on the fly or if you are in the Visual Studio resource editor it should have that as one of the styles. By default I think it's popup which will loose focus as soon as it appears because it's the style modal dialoges use not modeless ones. That and handle the WM_ACAD_KEEPFOCUS message by returning true and it should fix the problem.

MickD

  • Gator
  • Posts: 3290
  • (x-in)->[process]->(y-out)
Re: Win32 dialogs in ARX
« Reply #22 on: February 14, 2006, 03:54:01 PM »
Damn! so simple!
I tried every other setting you know except overlapped as I've read that overlapped windows are not recomended for dialogs.
I just gave myself a crash course on message hooks and found a few snippets I was going to implement today, if any one wants I'll post the links but hooks are not the best solution really and they use more resources to maintain the hook.
Thanks CB, that saved me a few hours.

I'll post a simple cpp framework skeleton of a modal an modeless dialogs after I do some code cleaning and 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

cornbread

  • Guest
Re: Win32 dialogs in ARX
« Reply #23 on: February 14, 2006, 04:16:13 PM »
Do you want my code for getting the handle of the session of Acad that your Arx is loaded into so you don't have to use adsw_acadMainWnd? adsw_acadMainWnd uses MFC that is why I ask.

MickD

  • Gator
  • Posts: 3290
  • (x-in)->[process]->(y-out)
Re: Win32 dialogs in ARX
« Reply #24 on: February 14, 2006, 04:24:10 PM »
Yes please, for completeness.
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

cornbread

  • Guest
Re: Win32 dialogs in ARX
« Reply #25 on: February 14, 2006, 04:39:31 PM »
The class:
Code: [Select]
#ifndef _MAINWIN_H_INCLUDED
#define _MAINWIN_H_INCLUDED

#include "windows.h"
#include "Psapi.h"

class MainWin{
public:
MainWin() : hWnd(NULL), procId(NULL){}
~MainWin(){}

HWND getMainWindowHandle(){
hWnd = NULL; procId = NULL;
procId = GetCurrentProcessId();
EnumWindows(matchProcessIdToWindow, (LPARAM)this);
return hWnd;
}

private:
DWORD procId;
HWND hWnd;
static BOOL CALLBACK matchProcessIdToWindow(HWND hWnd, LPARAM lParam) {
MainWin *mnw = reinterpret_cast<MainWin*>(lParam);
if ((GetWindowLong(hWnd,GWL_STYLE) & WS_VISIBLE)){
DWORD pidwin;
GetWindowThreadProcessId(hWnd, &pidwin);
if(pidwin==mnw->procId) {
mnw->hWnd = hWnd;
return FALSE;
}
}
return TRUE;
}
};


#endif

an example of it's use:
Code: [Select]
        MainWin mwn;

HWND AcadHwnd = mwn.getMainWindowHandle();

if(AcadHwnd){
HWND dlgHwnd = CreateDialog(_hdllInstance,
                  MAKEINTRESOURCE(IDD_DLG_WHATEVER),
                  AcadHwnd, (DLGPROC) DialogProc);
if(dlgHwnd){
ShowWindow(dlgHwnd, SW_SHOW);
}
}

MickD

  • Gator
  • Posts: 3290
  • (x-in)->[process]->(y-out)
Re: Win32 dialogs in ARX
« Reply #26 on: February 14, 2006, 06:03:37 PM »
Ok here it is, only a rough example to get you going. There is still a small issue when closing the modeless type that it sometimes minimises the main window which requires further investigation. I've also noticed this with the dialogs in AutoCAD sometimes, it can be anoying.

Remember to set your dialog window style to 'Overlapped' as cornbread pointed out above, not required for modal dilaogs but here I've used the same dialog class for both modal and modeless so it was changed from the standard Popup style.

the header file
Code: [Select]
/*----------------------------------------------------------------------------
 * Win32Dlg.h - by MickD Feb, 2006.
 * An *example only* of how to create and use win32 dialogs in ObjectARX.
 * Include this header in your acrxEntryPoint.cpp or similar file where
 * you will be creating your dialogs.
 *
 * Header file with the necessary items to create win32 api dialog boxes
 * Class - MainWin by Cornbread, get the handle(HWND)to the main application
 * window that is required when creating the dialogs.
 *
 * Window procedure prototypes - one for a modal dialog and one for a modeless
 * dialog. Add more for other dialogs as required.
 *---------------------------------------------------------------------------*/


#ifndef _WIN32DLG_H_INCLUDED
#define _WIN32DLG_H_INCLUDED

#include "windows.h" //required for ...windows!
#include "Psapi.h" //tools used for processes
#include "StdAfx.h" //also contains basic arx headers
#include "resource.h" //our dialog resources

//
class MainWin{
public:
MainWin() : hWnd(NULL), procId(NULL){}
~MainWin(){}

HWND getMainWindowHandle(){
hWnd = NULL; procId = NULL;
procId = GetCurrentProcessId();
EnumWindows(matchProcessIdToWindow, (LPARAM)this);
return hWnd;
}

private:
DWORD procId;
HWND hWnd;
static BOOL CALLBACK matchProcessIdToWindow(HWND hWnd, LPARAM lParam) {
MainWin *mnw = reinterpret_cast<MainWin*>(lParam);
if ((GetWindowLong(hWnd,GWL_STYLE) & WS_VISIBLE)){
DWORD pidwin;
GetWindowThreadProcessId(hWnd, &pidwin);
if(pidwin==mnw->procId) {
mnw->hWnd = hWnd;
return FALSE;
}
}
return TRUE;
}
};
//------------------< 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);

#endif //_WIN32DLG_H_INCLUDED

the .cpp file

Code: [Select]
/*----------------------------------------------------------------------------
 * Win32Dlg.cpp - by MickD Feb, 2006.
 * An *example only* of how to create and use win32 dialogs in ObjectARX.
 * Include the Win32Dlg.h header in your acrxEntryPoint.cpp or similar file where
 * you will be creating your dialogs.
 *
 * Window procedure implementation - one for a modal dialog and one for
 * a modeless dialog. Add more for other dialogs as required.
 *---------------------------------------------------------------------------*/

#include "Win32Dlg.h"

//=============< Dialog window procedures >=========================================
BOOL CALLBACK modelessDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
int len = 0;
int i = 0;
HWND hEdit;
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 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:
if(!DestroyWindow(hwnd))
MessageBox(NULL, "Failed to destroy window!", "KaBoom!",
MB_OK | MB_ICONEXCLAMATION);
break;
}
return TRUE;

case WM_ACAD_KEEPFOCUS:
return TRUE;
}
return FALSE;
};

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)
{
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)
{
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;
};

the code to handle and create the dialogs in response to commands from the user.
Code: [Select]
// ----- DCSArxProject7.dlgmdl command
// Command for modal dialog test "DLGMDL"
static void DCSArxProject7dlgmdl(void)
{
MainWin mwn;
HWND hwnd = mwn.getMainWindowHandle();

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)
{

MainWin mwn;
HWND hwnd = mwn.getMainWindowHandle();
HWND hModelessDlg = NULL;

// Add your code for command DCSArxProject7.dlgmdls here
if(_hModelessDlg==NULL)
{
hModelessDlg = CreateDialog(_hdllInstance, /*our dll handle*/
MAKEINTRESOURCE(IDD_DIALOG1),hwnd, (DLGPROC)modelessDlgProc);
if(_hModelessDlg != NULL)
{
ShowWindow(hModelessDlg, SW_SHOW);
}
else
{
MessageBox(hwnd, "CreateDialog returned NULL", "Warning!", 
MB_OK | MB_ICONINFORMATION);
}
}
else
{
ShowWindow(hModelessDlg, SW_SHOW);
}
}
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: 3290
  • (x-in)->[process]->(y-out)
Re: Win32 dialogs in ARX
« Reply #27 on: August 15, 2006, 05:38:24 PM »
I thought I'd post a sample of an actual dialog I'm using in a current project, all in win32.
I can only get int values from the edit box at the moment as that's all that's available in the api but I will be either catching the key events or sub classing the edit box window to handle alphabetical (unwanted) characters as soon as I get the functions and other things tidied up a bit.

The window procedure to handle windows messages (events) -
Code: [Select]
BOOL CALLBACK modifyDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
BOOL * xltd = FALSE;
// make these static to keep variable values between instances:
static int cutoffset = 0;
static int polycutoffset = 0;
static int polycutdepth = 1000;
static int drilldia = 22;
static int drilldepth = 50;
static int slotlength = 50;

switch(Message)
{
case WM_INITDIALOG:
// set the current values for the edit controls:
SetDlgItemInt(hwnd,IDC_EDIT_CUTOFF,cutoffset,TRUE);
SetDlgItemInt(hwnd,IDC_EDIT_POLYOFF,polycutoffset,TRUE);
SetDlgItemInt(hwnd,IDC_EDIT_POLYLEN,polycutdepth,TRUE);
SetDlgItemInt(hwnd,IDC_EDIT_DIA,drilldia,TRUE);
SetDlgItemInt(hwnd,IDC_EDIT_DEEP,drilldepth,TRUE);
SetDlgItemInt(hwnd,IDC_EDIT_SLOTL,slotlength,TRUE);
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_BTN_CUTL:
cutoffset = (int)GetDlgItemInt(hwnd,IDC_EDIT_CUTOFF,xltd,TRUE);
// call our cutting function:
//************************ here **********
break;
case IDC_BTN_CUTF:
cutoffset = (int)GetDlgItemInt(hwnd,IDC_EDIT_CUTOFF,xltd,TRUE);
// call our cut at face function:
//************************ here **********
break;
case IDC_BTN_POLYCUT:
polycutoffset = (int)GetDlgItemInt(hwnd,IDC_EDIT_POLYOFF,xltd,TRUE);
// call our poly cutting function:
//************************ here **********
break;
case IDC_BTN_SLOT:
drilldia = (int)GetDlgItemInt(hwnd,IDC_EDIT_DIA,xltd,TRUE);
drilldepth = (int)GetDlgItemInt(hwnd,IDC_EDIT_DEEP,xltd,TRUE);
slotlength = (int)GetDlgItemInt(hwnd,IDC_EDIT_SLOTL,xltd,TRUE);
// call our slotting function:
//************************ here **********
break;
case IDC_BTN_DRILL:
drilldia = (int)GetDlgItemInt(hwnd,IDC_EDIT_DIA,xltd,TRUE);
drilldepth = (int)GetDlgItemInt(hwnd,IDC_EDIT_DEEP,xltd,TRUE);
slotlength = (int)GetDlgItemInt(hwnd,IDC_EDIT_SLOTL,xltd,TRUE);
EndDialog(hwnd, IDC_BTN_DRILL);
// call our drilling function:
DrillHoles(drilldia,drilldepth);
break;
case IDCANCEL:
EndDialog(hwnd, IDCANCEL);
break;
}
break;
default:
return FALSE;
}
return TRUE;
};


and the image -
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

Draftek

  • Water Moccasin
  • Posts: 1501
Re: Win32 dialogs in ARX
« Reply #28 on: August 16, 2006, 07:50:54 AM »
Very nice and great topic.

Thanks
Soli Deo Gloria

MickD

  • Gator
  • Posts: 3290
  • (x-in)->[process]->(y-out)
Re: Win32 dialogs in ARX
« Reply #29 on: August 16, 2006, 06:26:03 PM »
The thing I like about win32 is you can always see exactly what's going on, MFC does it's best to hide it all with macro's like DDX (do data exchange)  and message maps etc which are basically doing exactly the same thing. It seems like a lot of work to make things easier, if you had to write MFC by hand (not use the class wizard) I reckon you would find it a real chore.
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