How to stop Stephen Bullen's CFormChanger from minimizing as an MDItitle bar?

J

Jim Luedke

I’m running Excel 2002 in Win 2000.

Everyone ought to know about Stephen Bullen’s fantastic CFormChanger.

It helps bring UserForm a lot closer to a normal Windows app, letting
you add such standard features as modelessness, resizeability, icons,
caption, min/max buttons, minimizing to the Windows Taskbar, etc.

But, since day 1 for me, it sometimes gets into a state whereby it
always minimizes to a little title bar in the L.R. corner of the
screen *above* the Windows Taskbar. (But it puts a button on the
Taskbar too.) This could be due something I've changed in his code.

After much reading, I suspect it may be an MDI-style minimized title
bar.

Besides failing to understand how an OS can even permit a (what I
understand to be) Win 3.1 artifact to appear, say, 200 years after the
Industrial Revolution, my questions are many.

The most important is: How do I get rid of it?

***

Optionally, for anyone interested in learning a bit about Windows form
management travails, read on (O King Eternal):

Blogs seem to suggest it might not be entirely Microsoft’s fault for
retaining this artifact. One thread seems to suggest that, with the
introduction of the Desktop and Taskbar in Windows 95, Windows had to
do something with the vestigial MDI-style title bar. It seems MS
couldn’t just hide it, because many apps depended on its staying real
and visible. MS tried moving it to various exotic locations, like
-32000,-32000, but some apps still choked on it.

So it seems the Redrum, WA authorities finally decided on 3000,3000 as
an ideal compromise position to park the title bar. (Supposedly, if
your screen exceeds 3K shmixels, or you can rig up a battery of
monitors, you’ll see all your minimized apps parked out there in MS’s
Van Allen Belt.)

Some blogs say the little bar is sized at 160x31. (That might be at
high res, because on my screen (1024x768?), it’s 120x18).

By the way, you implement Bullen’s CFormChanger with something like:

Dim FormChanger as CFormChanger

Set FormChanger = New CFormChanger
With FormChanger
Set .Form = Me
.ShowMaximizedButton = True
.ShowMinimizedButton = True
.WhileYoureUpGetMeABeer = True
...etc.
End With

So I figure, I’ve got to hook into Windows messaging, or better use a
Resize event, or do something to hide or move the pesky bar.

Ideally, you'd want to do it at the class level, within the
CFormChanger Class Module, right?

So I took some tips from Chip Pearson’s *tremendous* site, which
everyone also ought to know about:

www.cpearson.com/excel/AppEvent.aspx

Within CFormChanger's module I tried:

Private WithEvents App As Application

Private Sub Class_Initialize()
Set App = Application
End Sub

Private Sub App_WindowResize(ByVal Wb As Workbook, ByVal Wn As
Window)
etc.

But this event never seems to fire for me. Why? (The runtime value of
Application is real--it pops up as I think "Microsoft Excel").

So then I tried UserForm’s own resize event, which of course fires
fine on minimize. But the problems intensify. If I try:

Private Sub UserForm_Resize()
With UserForm1
If (.Height <= 31) And (.Width <= 160) Then
.Top = 3000
.Left = 3000
End If
End With
End Sub

I get:

“Can't move or resize form while Minimized or Maximized”.

I mean, huh? I thought I just learned Windows *itself* moves everyone
on minimize? If I try:

With UserForm1
.Visible = ((.Height > 31) Or (.Width > 160))
End With

I get this gem--uninterpretable by the average gibbon:

“Function or interface marked as restricted, or the function uses
an Automation type not supported in Visual Basic”

and so on.

Is the problem rather at the Excel level? Some people seem to say
Excel is an MDI application. Is *that* true? If so, is there some
WS_KILL_MDI_BEHAVIOR property I can set?

Finally, while my UserForm/CFormChanger app is running, I do
frequently minimize it, then go and work in the VBA Editor. I figure
that's gotta be a challenge to Excel, what with two ancillary
workspaces hanging off it; maybe some pointers get croxxed?

Thanks all very much.

***
 
J

Jim Luedke

Correction: The little title bar is in the lower *left* corner. On my
screen, it's at position 567,0.

***
 
P

Peter T

it sometimes gets into a state whereby it
always minimizes to a little title bar in the L.R. corner of the
screen *above* the Windows Taskbar

That's "floating" and will occur consistently (not sometimes assuming
consistent code)

From memory Stephen Bullen's formsizer only minimises the form to a floating
state, rather than to the taskbar. If you want the form to appear in the
taskbar when minimised try something like this (look for an Excel like icon
in the taskbar when minimised, or replace with your own icon)

' in a normal module

Sub ShowForm()
UserForm1.Show vbModeless
End Sub

' in userform1

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function GetWindowLong Lib "user32" Alias _
"GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias _
"SetWindowLongA" (ByVal hwnd As Long, _
ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function DrawMenuBar Lib "user32" ( _
ByVal hwnd As Long) As Long
Private Declare Function ShowWindow Lib "user32" ( _
ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Private Declare Function IsIconic Lib "user32" (ByVal hwnd As Long) As Long


Private Const WS_MAXIMIZEBOX As Long = &H10000
Private Const WS_MINIMIZEBOX As Long = &H20000
Private Const GWL_STYLE As Long = -16
Private Const GWL_EXSTYLE As Long = -20
Private Const WS_EX_APPWINDOW As Long = &H40000
Private Const WS_EX_WINDOWEDGE As Long = &H100&
Private Const WS_EX_DLGMODALFRAME As Long = &H1&
Private Const ws_EX_AWD = WS_EX_APPWINDOW _
Or WS_EX_WINDOWEDGE Or WS_EX_DLGMODALFRAME
Private Const SW_HIDE As Long = 0
Private Const SW_MINIMIZE As Long = 6

Private mFrmHwnd As Long

Private Sub UserForm_Activate()

SetWindowLong mFrmHwnd, GWL_EXSTYLE, ws_EX_AWD
End Sub


Private Sub UserForm_Initialize()
Dim nStyle As Long
mFrmHwnd = FindWindow("ThunderDFrame", Me.Caption) ' "ThunderXFrame" in
xl97

nStyle = GetWindowLong(mFrmHwnd, GWL_STYLE) Or WS_MINIMIZEBOX
' nStyle = nStyle Or WS_MAXIMIZEBOX

SetWindowLong mFrmHwnd, GWL_STYLE, nStyle
DrawMenuBar hwnd

End Sub

Private Sub UserForm_Resize()

If IsIconic(mFrmHwnd) Then
ShowWindow mFrmHwnd, SW_HIDE
ShowWindow mFrmHwnd, SW_MINIMIZE
End If

End Sub


Obviously this is the basic calls only, you'll probably want to rearrange
it. Eg not much to do to incorporate into CFormChanger - just call
SetWindowLong mFrmHwnd, GWL_STYLE, nStyle after the form has been shown and
the resize event code.

MDI-style title bar
not sure what you are talking about, an MDI (multiple doc interface) form
(ie window) is "contained" in another window (not to be confused with
parent).

I’ve got to hook into Windows messaging

Don't go there, at least not in VBA and definately not if you/anyone is
likely to break into running code unless you want to GPF. (FWIW There is a
helper C-dll out there that can be used in VBA to trap windows events)

Regards,
Peter T



I’m running Excel 2002 in Win 2000.

Everyone ought to know about Stephen Bullen’s fantastic CFormChanger.

It helps bring UserForm a lot closer to a normal Windows app, letting
you add such standard features as modelessness, resizeability, icons,
caption, min/max buttons, minimizing to the Windows Taskbar, etc.

But, since day 1 for me, it sometimes gets into a state whereby it
always minimizes to a little title bar in the L.R. corner of the
screen *above* the Windows Taskbar. (But it puts a button on the
Taskbar too.) This could be due something I've changed in his code.

After much reading, I suspect it may be an MDI-style minimized title
bar.

Besides failing to understand how an OS can even permit a (what I
understand to be) Win 3.1 artifact to appear, say, 200 years after the
Industrial Revolution, my questions are many.

The most important is: How do I get rid of it?

***

Optionally, for anyone interested in learning a bit about Windows form
management travails, read on (O King Eternal):

Blogs seem to suggest it might not be entirely Microsoft’s fault for
retaining this artifact. One thread seems to suggest that, with the
introduction of the Desktop and Taskbar in Windows 95, Windows had to
do something with the vestigial MDI-style title bar. It seems MS
couldn’t just hide it, because many apps depended on its staying real
and visible. MS tried moving it to various exotic locations, like
-32000,-32000, but some apps still choked on it.

So it seems the Redrum, WA authorities finally decided on 3000,3000 as
an ideal compromise position to park the title bar. (Supposedly, if
your screen exceeds 3K shmixels, or you can rig up a battery of
monitors, you’ll see all your minimized apps parked out there in MS’s
Van Allen Belt.)

Some blogs say the little bar is sized at 160x31. (That might be at
high res, because on my screen (1024x768?), it’s 120x18).

By the way, you implement Bullen’s CFormChanger with something like:

Dim FormChanger as CFormChanger

Set FormChanger = New CFormChanger
With FormChanger
Set .Form = Me
.ShowMaximizedButton = True
.ShowMinimizedButton = True
.WhileYoureUpGetMeABeer = True
...etc.
End With

So I figure, I’ve got to hook into Windows messaging, or better use a
Resize event, or do something to hide or move the pesky bar.

Ideally, you'd want to do it at the class level, within the
CFormChanger Class Module, right?

So I took some tips from Chip Pearson’s *tremendous* site, which
everyone also ought to know about:

www.cpearson.com/excel/AppEvent.aspx

Within CFormChanger's module I tried:

Private WithEvents App As Application

Private Sub Class_Initialize()
Set App = Application
End Sub

Private Sub App_WindowResize(ByVal Wb As Workbook, ByVal Wn As
Window)
etc.

But this event never seems to fire for me. Why? (The runtime value of
Application is real--it pops up as I think "Microsoft Excel").

So then I tried UserForm’s own resize event, which of course fires
fine on minimize. But the problems intensify. If I try:

Private Sub UserForm_Resize()
With UserForm1
If (.Height <= 31) And (.Width <= 160) Then
.Top = 3000
.Left = 3000
End If
End With
End Sub

I get:

“Can't move or resize form while Minimized or Maximized”.

I mean, huh? I thought I just learned Windows *itself* moves everyone
on minimize? If I try:

With UserForm1
.Visible = ((.Height > 31) Or (.Width > 160))
End With

I get this gem--uninterpretable by the average gibbon:

“Function or interface marked as restricted, or the function uses
an Automation type not supported in Visual Basic”

and so on.

Is the problem rather at the Excel level? Some people seem to say
Excel is an MDI application. Is *that* true? If so, is there some
WS_KILL_MDI_BEHAVIOR property I can set?

Finally, while my UserForm/CFormChanger app is running, I do
frequently minimize it, then go and work in the VBA Editor. I figure
that's gotta be a challenge to Excel, what with two ancillary
workspaces hanging off it; maybe some pointers get croxxed?

Thanks all very much.

***
 
J

Jim Luedke

Peter:

Thanks *very* much for the help. I'll give it all a try.

***

I guess I shouldn't have said "Windows messaging". What I actually
meant to say was, simply using Windows API functions.

Thanks again.

***
 
J

Jim Luedke

Peter:

Works like a charm.

(Except, it's:

Private Sub UserForm_Resize()
If IsIconic(hWnd) Then
Call ShowWindow(hWnd, SW_HIDE)
' Call ShowWindow(hWnd, SW_MINIMIZE)
End If
End Sub

If I execute the SW_MINIMIZE too, it un-hides again.)

Thanks a-much.

***
 
P

Peter T

If I execute the SW_MINIMIZE too, it un-hides again.)

It shouldn't unhide it, merely minimize it to the taskbar. Are you using the
example exactly as I posted it?

If you only do SW_HIDE you won't be able to manually restore it, only way
would be to have stored the form's window handle in a way that be retrieved
in a normal module and do:
ShowWindow hwnd, SW_NORMAL ' 1

Regards,
Peter T
 
J

Jim Luedke

Peter:

First, thanks for bringing my attention to your reply via that other
thread.

***

No, SW_HIDE without SW_MINIMIZE works just fine. The UserForm restores
fine too, by clicking on its Toolbar button.

(Of course, since I'm a keyboard maven, I'd rather use Alt+Tab (or Alt
+Esc) to get it back, which is what my other thread's about.)

Bullen and I do play around with Win API stuff a bit in his
CFormChanger class. But I certainly don't, say, muck around with the
actual minimize/restore process (apart from your code).

I use your code verbatim (with the SW_MINIMIZE line commented out) in
the UserForm event.

FWIW, Bullen uses ShowWindow in one other place: in CFormChanger, on
startup, to implement the Taskbar button, which I guess is one of
those style items that won't update unless you hide/reshow the window:

StyleFlags = StyleFlags Or WS_EX_APPWINDOW
Call ShowWindow(MyHWnd, SW_HIDE)
Call SetWindowLong(MyHWnd, GWL_EXSTYLE, StyleFlags)
Call ShowWindow(MyHWnd, SW_SHOW)

So your remarks are interesting.

And I'm about to try your great GWL_HWNDPARENT stuff re. the Alt+Tab
problem.

***
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top