Author Topic: Activate new window  (Read 9589 times)

0 Members and 1 Guest are viewing this topic.

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16721
  • Superior Stupidity at its best
Activate new window
« on: November 25, 2003, 03:06:04 PM »
Ok, anyone out there familiar with API please help....
I am in need of making the AutoCAD current drawing the current window AFTER I specify a new application window as HWND_TOPMOST.

Here is the scenario....
I am developing an external app that runs in windows alongside of AutoCAD. I need this app to stay on top so that the user can change the settings on the fly AND be visible so the user can select the commands associated with the program.

I have been able to set the HWND_TOPMOST setting of the external dialog, but whenever I send the commands to AutoCAD, I have to click 2 or 3 times in the drawing window to make it current so I can use the program. This is really a frustrating proposition.

I would like to have the external app remain on top, but be inactive and the AutoCAD current drawing to become active so I don't have to click 2 or 3 times in the drawing, then inadvertently clicking in the wrong place and having to start again.

Am I making myself clear?
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16721
  • Superior Stupidity at its best
Activate new window
« Reply #1 on: November 26, 2003, 02:37:21 PM »
Ok just to let you guys know... you are off the hook... I received an email from someone I didn't know (maybe they didn't want to offend me by making me feel inferior) Anyway the answer is:
Code: [Select]

Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Public Declare Function SetForegroundWindow Lib "user32" (ByVal hWnd As Long) As Boolean

SetForegroundWindow FindWindow(vbNullString, AcadApplication.Caption)


He just pointed me in the right direction and the rest was mine...

This API stuff is awesome!!
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

daron

  • Guest
Activate new window
« Reply #2 on: November 26, 2003, 02:48:23 PM »
Well, if you didn't find out, I was thinking of sending you to vbdesign.net. I have some questions. What are the uses of programming the API and how do you go about understanding how?

SMadsen

  • Guest
Activate new window
« Reply #3 on: November 26, 2003, 03:01:33 PM »
KEB, just curious, don't you have to take specific action to keep the inactivated window on top?
I thought SetForegroundWindow would put the whdl in front, while e.g. PutFocus would simply allow it to be handled without put in front.

SMadsen

  • Guest
Activate new window
« Reply #4 on: November 26, 2003, 03:03:25 PM »
Daron, check out http://www.allapi.net. They have some great (and free) resources.

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16721
  • Superior Stupidity at its best
Activate new window
« Reply #5 on: November 26, 2003, 03:08:21 PM »
SMadsen, the inactive window is behind the controlling application. The controlling application has the HWND_TOPMOST bit set and as such will always remain on top (similar to WinZip when you select the "Always on Top" checkbox).
The topmost window can be inactive, and regardless of which window is the active one, it will remain on top but greyed out.
What I needed was for the topmost application to automatically make the AutoCAD window the active window, since it was done outside of AutoCAD, the process was handled through API functions.
I have already implemented the function calls in my program and it works wonderfully.

Daron, API programming allows you to use ANY function defined as portable within ANY dll,exe,odl,arx,tlb, and any other format of executable binary file you can imagine.

Think of the C and C++ functions that you are aware of. All you do is declare that function with the appropriate arguments and types within VBA and then you can simply call that C or C++ function.

For example, you want to change the title of AutoCAD to reflect your addon package defined in VBA. In plain VBA the AcadApplication.Caption is 'read only', so you can't apply a new caption with AcadApplication.Caption = "New Caption" BUT you can call the SetWindowText C++ command by declaring it and set the caption there. This is powerful stuff that can get you into trouble if you are not sure what you are doing.

Check out this post to see what I mean.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

SMadsen

  • Guest
Activate new window
« Reply #6 on: November 26, 2003, 03:29:17 PM »
Quote from: KEB
I have already implemented the function calls in my program and it works wonderfully.
Sounds great. Gotta check it out sometime soon.
On the Mac one could specify a always-on-top window by its window proc. I got confused by the Z ordering in Windows where it seems you can force windows on top of such a window.

Quote from: KEB
This is powerful stuff that can get you into trouble if you are not sure what you are doing.
Yeah .. and in trouble with your colleagues by making AutoCAD play music to each command :)

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16721
  • Superior Stupidity at its best
Activate new window
« Reply #7 on: November 26, 2003, 03:35:28 PM »
I hadn't though of that.... Maybe make a little program that ran in the background that waited every 5 or 10 minutes and then played their "you got mail" wave. They would wonder what the heck was going on.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

SMadsen

  • Guest
Activate new window
« Reply #8 on: November 26, 2003, 03:40:07 PM »
Here's one for simple wav's  :)

Code: [Select]
Private Const SND_ASYNC = &H1         '  play asynchronously
Private Const SND_FILENAME = &H20000  '  file name
Private Declare Function PlaySound Lib "winmm.dll" (ByVal lpszName As String, ByVal hModule As Long, ByVal dwFlags As Long) As Long

Private Sub PlayItSam()
    PlaySound "C:\WINDOWS\MEDIA\TADA.WAV", ByVal 0&, SND_FILENAME Or SND_ASYNC
End Sub

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16721
  • Superior Stupidity at its best
Activate new window
« Reply #9 on: November 26, 2003, 04:03:15 PM »
Now all we need is a timer.....

I was thinking about....

Code: [Select]

Declare Function SetTimer Lib "user32" (ByVal Hwnd As Long, ByVal IdEvent As Long, ByVal seconds As Long, ByVal Func As Variant) As Long
Sub NewTimer()
Dim RVal As Long
 RVal = SetTimer(NULL, 1, 30, NULL)
End Sub

But I am getting an invalid use of NULL error.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

daron

  • Guest
Activate new window
« Reply #10 on: November 26, 2003, 04:24:27 PM »
That is funny.

SMadsen

  • Guest
Activate new window
« Reply #11 on: November 26, 2003, 05:14:20 PM »
Hmm, can't get it to work either - the SetTimer thing that is

SomeCallMeDave

  • Guest
Activate new window
« Reply #12 on: November 26, 2003, 07:53:37 PM »
I think SetTimer needs a callback function.  Something like
 
in a module
Code: [Select]

Option Explicit
Public Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Public Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long

Public Function TimerProc() As Long
  MsgBox "Timer Fired"
End Function

Public Function TimerSetup(pInterval As Long) As Long
  Dim lngRet As Long
  lngRet = SetTimer(0&, 0&, pInterval, AddressOf TimerProc)
  TimerSetup = lngRet
End Function

Public Function StopTimer(pTimer As Long)
  KillTimer 0&, pTimer
End Function


In a form, I put
Code: [Select]

Option Explicit
Dim hwndTimer As Long
Private Sub Command1_Click()
 hwndTimer = Module1.TimerSetup(2000)
End Sub

Private Sub Command2_Click()
  Module1.StopTimer hwndTimer
End Sub

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16721
  • Superior Stupidity at its best
Activate new window
« Reply #13 on: November 27, 2003, 06:54:52 AM »
Beautiful!!!
Now all I need to do is make it transparent to the user....
 :twisted:  :twisted:  :twisted:  :twisted:
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

SMadsen

  • Guest
Activate new window
« Reply #14 on: November 27, 2003, 07:10:44 AM »
SCD, thanks. I tried handing SetTimer a proc in the same manner but couldn't figure out why AddressOf returned an error: expression expected.
Isn't there something about pointers not being a valid datatype in VBA?

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16721
  • Superior Stupidity at its best
Activate new window
« Reply #15 on: November 27, 2003, 09:38:11 AM »
AddressOf is not valid in VBA, there is a workaround on the vbdesign.net website
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

SMadsen

  • Guest
Activate new window
« Reply #16 on: November 27, 2003, 09:46:16 AM »
Thought as much. It seemed a bit indigestible in VBA.
Oh, I better quit this thread now before I actually manage to learn VBA  :shock:

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16721
  • Superior Stupidity at its best
Activate new window
« Reply #17 on: November 27, 2003, 10:29:30 AM »
Try this in VBA to return the AddressOf ...

Public Function MyAddressOf(sFuncName As String) As Long
' This function Returns a function pointer of a VBA public function.
' Since the VB AddressOf operator which is not supported in VBA, call this
' function passing in the name of the function you want the pointer to.        
' Generic return result so we can test our function calls for errors    

 Dim lResult As Long
' To hold the handle to the current project    
 Dim lHproject As Long
' To hold the ID of our function name as it is known by the system
Dim sFuncID As String
' To hold the final result (the return value of MyAddressOf)    
' It is the same as if we had used the standard VB AddressOf function    
' but remember, that is not supported in VBA

Dim lFuncPtr As Long
' The function name you passed in when you called MyAddressOf needs    
' to be converted to Unicode in order for it to be found by GetFuncID    
' This will hold that conversion

Dim sFuncNameUnicode As String
' Convert the passed in function name (the one we want the address of) to Unicode
sFuncNameUnicode = StrConv(sFuncName, vbUnicode)            
' Get the current VBA project handle
Call GetCurrentVbaProject(lHproject)            
' Make sure we got a project handle
If lHproject <> 0 Then
' Get the VBA function ID (this is the ID of the function we passed in to MyAddressOf)
lResult = GetFuncID(lHproject, sFuncNameUnicode, sFuncID)                
' Again, check for an error so we don't try to get a pointer to    
' a non-existent function.

If lResult = NO_ERROR Then
' Get the function pointer.
lResult = GetAddr (lHproject, sFuncID, lFuncPtr)                      
If lResult = NO_ERROR Then
' Return the pointer to the function we passed in
MyAddressOf = lFuncPtr      
End If    
End If    
End If      
End Function

You will need to replace the AddressOf call in the code with MyAddressOf to make it work....
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

SMadsen

  • Guest
Activate new window
« Reply #18 on: November 27, 2003, 10:49:02 AM »
Cool. That's a keeper for future reference. Thanks.

Off to Vegas for now. See you guys in week or so!

Mark

  • Custom Title
  • Seagull
  • Posts: 28685
Activate new window
« Reply #19 on: November 27, 2003, 12:38:36 PM »
>Off to Vegas for now. See you guys in week or so!
Enjoy, I know I would. :D
TheSwamp.org  (serving the CAD community since 2003)

SMadsen

  • Guest
Activate new window
« Reply #20 on: November 27, 2003, 12:45:03 PM »
Thanks Mark.
15 hours till the flight, though, so just got time to browse a bit

Mark

  • Custom Title
  • Seagull
  • Posts: 28685
Activate new window
« Reply #21 on: November 27, 2003, 12:55:03 PM »
Bring back lots of info for us to read. <g>
TheSwamp.org  (serving the CAD community since 2003)

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16721
  • Superior Stupidity at its best
Activate new window
« Reply #22 on: November 27, 2003, 12:56:20 PM »
Vegas!!! Welcome to the USA!!!!

(leave your cash at the craps table)
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

SMadsen

  • Guest
Activate new window
« Reply #23 on: November 27, 2003, 12:59:15 PM »
Quote from: Mark Thomas
Bring back lots of info for us to read. <g>

Huh? Is it the purpose of AU to study something? C'mon, it's Las Vegas .. I expect to return with a trunk full of cash!

SMadsen

  • Guest
Activate new window
« Reply #24 on: November 27, 2003, 01:02:06 PM »
Or is it just to return in a trunk? :?

Mark

  • Custom Title
  • Seagull
  • Posts: 28685
Activate new window
« Reply #25 on: November 27, 2003, 01:04:45 PM »
> I expect to return with a trunk full of cash!

good luck them. :D
TheSwamp.org  (serving the CAD community since 2003)

daron

  • Guest
Activate new window
« Reply #26 on: November 29, 2003, 01:13:31 AM »
Hah! I'll see you there. I'll probably be the only one trying to apply what I learn. I don't really care much for Vegas. Been there twice and was less impressed the second time than I was the first time.