Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

MsgBox format 7

Status
Not open for further replies.

deepsheep

Programmer
Sep 13, 2002
154
CA
I have a msgbox in a VB6 application that is doing what I want. It displays a message and stays on top of everything (by vbSystemModal option) until the 'OK' is pressed.

However, I want the text to be bigger in the msgBox. I want it to be big enough that if someone wanders past the screen, they can read it easily.

I tried changing the font size on the form and it didn't work.

Any ideas?
Thanks!
 
>by vbSystemModal option

Strange because that is not an option with a true MsgBox. You may have that option if you have already created a Form to act as a message box.

If it is a true MsgBox the text on it is in a fixed/ standard format which cannot be modified easily.

If you require a message box which displays data in a non-standard manner/ format I recommend you create a Form to do it.
 
<that is not an option with a true MsgBox
The constant "vbSystemModal" (=4096) may be specified with the MsgBox function.

<I recommend you create a Form to do it
Which doesn't have the system modal option.

ds, in order to do what you want, you'll need to subclass the MsgBox function. This should get you started. You'll probably need to learn something about how the code works before you can get it to work the way you want.

HTH

Bob
 
>The constant "vbSystemModal" (=4096) may be specified with the MsgBox function.

And so it is. Apologies DeepSh and thanks Bob, I was not aware of that one; a star for you.
 
Thanks for the star, Hugh. :) Ds, it's important to be very careful when you use this, by the way. A good example of when Windows uses it is when you run low on memory (which happens when you do something like run AOL for three days straight). The idea is that the user will want to know this no matter what the application context, because this is a warning about a general system issue that could affect every application. If you are using this in an application context and taking over another application context, that's considered bad manners. On the other hand, bad manners are sometimes exactly what is required. Just not very often. :)
 
>you'll need to subclass the MsgBox function

Or you can use the slightly easier timer or (my preferred) CBT-based techniques illustrated here: thread222-662729

Although the examples are being used against an InputBox they are equally valid against a MessageBox

But I second HughLerwill's suggestion that you create your own form to look like a message box.
 
<But I second HughLerwill's suggestion that you create your own form to look like a message box.

How can you make the form system modal?
 
<techniques illustrated here
Ok, strongm, I've done a little perusing, and I think I get this. The CBT hook idea is cleaner really than the timer, because the timer relies on the idea that it will take less than one millisecond to activate the window in question and expose a handle (which it probably will, of course), whereas the hook sets up a sort of mini-event-based-monitoring system and is therefore a more integrated process.

Also, the code I posted is more complex because it starts when the window is created and creates it differently, whereas yours diverts to a handler when the window is activated, and then alters the already activated window.

Is that about it?
 
>How can you make the form system modal?

I wouldn't. System modal is evil. And Microsoft concur, removing system modal functionality from Win32 as far back as Windows2000, possibly Windows 98 (they removed, for example, the SetSysModal API call). And even as far back as the Windows Interface Guidelines released for Windows 95 they advise developers to "avoid system modal ... [] ... windows, except in the case of possible loss of data". The so-called system modal windows nowadays are really no such thing - they are basically application modal, but set to the top of the Z-order

>Is that about it?

Yep

of course, if you actually need to be able to provide custom responses to actions in the message box (e.g. to button clicks), then the subclassing technique becomes more attractive
 
>System modal is evil.

My ignorance was bliss it appears. Now I just have something else I have to remember to forget...
 
<they are basically application modal, but set to the top of the Z-order

Well, yes, I get that. But the point is that OP is looking for this functionality. How do you get it on a form? If you just use ZOrder, other application windows still paint over it.
 

You can always make the Form (that would be the one pretending to be a message box) StayOnTop

In the Module:
Code:
Option Explicit

Public Declare Function SetWindowPos& Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long)

Const HWND_TOPMOST = -1
Const SWP_NOSIZE = &H1
Const SWP_NOMOVE = &H2

Public Sub StayOnTop(frm As Form)

SetWindowPos frm.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE

End Sub

Place this code in the Resize event of the form you want on top:
Code:
Private Sub Form_Resize()
    StayOnTop Me
End Sub

Would that work?


Have fun.

---- Andy
 
Yep, that would be pretty close. I suspect I might add

Private Sub Form_Deactivate()
Me.SetFocus
End Sub

to the form as well
 
Wow, thanks guys. I've been out of the office all morning and this is alot to digest.

My application is as follows:
I'm monitering a piece of equipement. If a certain state is reached the operator MUST be alerted, even if they are doing something else.
My solution was to have a message box that pops up on top of everything else and doesn't go away until you hit OK. It seemed to do what I needed, except for the print being smaller than I wanted.

I'll be trying some of your feedback a bit later. I'll try to let you know what I ended up doing.
Thanks!
 
Impressive. The only thing is that Deactivate doesn't fire if you activate a window outside of the application, so the window is in the deactivated color.
 
>the window is in the deactivated color

I think that's pretty much what the 'system modal' MsgBox does as well ...
 
All right. I thought I would see if I could put together a msgbox function that allows you to set fonts, using strongm's CBT hooking code as a startoff point. The code hangs (kicks me out of the IDE) when I invoke the standard msgbox function in the wrapper.

Here's the code in the form:
Code:
[COLOR=blue]Private Sub Command1_Click()
myMsgBox "Hello Everyone", vbOKOnly, 12, True, True, True, "Times New Roman", "Test"
End Sub
[/color]
Here's the code in the module:
Code:
[COLOR=blue]Option Explicit

Const FW_NORMAL = 400
Const FW_BOLD = 700

' Necessary constants  for hooking
Private Const HCBT_ACTIVATE = 5
Public Const WH_CBT = 5

' Working variables that require global scope in hooking module
Private hFont As Long
Private hHook As Long

' The API declarations we need
Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function CreateFont Lib "gdi32" Alias "CreateFontA" (ByVal nHeight As Long, ByVal nWidth As Long, ByVal nEscapement As Long, ByVal nOrientation As Long, ByVal fnWeight As Long, ByVal fdwItalic As Boolean, ByVal fdwUnderline As Boolean, ByVal fdwStrikeOut As Boolean, ByVal fdwCharSet As Long, ByVal fdwOutputPrecision As Long, ByVal fdwClipPrecision As Long, ByVal fdwQuality As Long, ByVal fdwPitchAndFamily As Long, ByVal lpszFace As String) As Long

' Wrapper for the normal MsgBox function
Public Sub myMsgBox(Prompt As String, Buttons As VbMsgBoxStyle, fSize As Integer, fBold As Boolean, fItalic As Boolean, fULine As Boolean, fFaceName As String, Optional Title As String, Optional HelpFile As String, Optional Context As Long)
    hFont = CreateFont(fSize * -20 / Screen.TwipsPerPixelY, 0, 0, 0, FW_BOLD, 0, 0, 0, 0, 0, 0, 0, 0, "Arial" & Chr(0))
    hHook = SetWindowsHookEx(WH_CBT, AddressOf CBTProc, App.hInstance, 0)
    [COLOR=red]MsgBox Prompt 'code hangs here[/color]
End Sub

Private Function CBTProc(ByVal lMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Dim hwndMsgBox As Long
    If lMsg = HCBT_ACTIVATE Then
        hwndMsgBox = FindWindowEx(wParam, 0, "#32770", "") ' get the msgbox window, which has the obscure name of "#32770" as opposed to something more normal like "Edit"
        If hwndMsgBox Then SendMessage hwndMsgBox, WM_SETFONT, hFont, True ' Do your stuff here to modify the window
        UnhookWindowsHookEx hHook ' Immediately unhook
    End If
    CBTProc = 0 ' allow operation to continue
End Function
[/color]
I'm pretty much going by things that I've read here and there, so there are plenty of things I'm not sure of. In particular, I'm not sure whether I'm converting points to pixels properly, whether I'm handing the typeface string correctly, whether it's acceptable to pass 0 to a byte type, whether hFont should really be a big negative integer, and whether "#32770" is really the string that names the MsgBox window. Of course, I could be doing something else wrong too. Can anyone enlighten me?

TIA

Bob
 
Curiouser and curiouser...

Ok, the problem appears to be somewhere in the CBTProc proc. First, FindWindowEx returns 0, giving rise to the idea that "#32770" is not the name of the MsgBox box. However, the really strange thing to me is this. If hwndMsgBox is in fact 0, as it checks out to be, then SendMessage ought not to get executed. But if I comment out the SendMessage, I get the normal message box, and if I leave it in, the IDE shuts down. This is also true if I send a message other than WM_SETFONT, but I don't understand how the SendMessage code even gets executed if the hwndMsgBox evaluates to false, and I don't understand why I get different behavior when I comment out the SendMessage if it isn't in fact getting executed in some way. Anybody help on this?

TIA

Bob
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top