Bug in UserLibrary>>messageBox:text:caption:style:icon:instance:

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Bug in UserLibrary>>messageBox:text:caption:style:icon:instance:

Dmitry Zamotkin
Cyclic errors are appeared when there are no active application window
yet. Parent window handle should points to desktop:

messageBox: anExternalHandle text: textString caption: captionString
style: styleInteger icon: iconIdentifier instance: hInstance
        | iconId struct wasDisabled hWnd response isTaskModal |
        isTaskModal := styleInteger allMask: MB_TASKMODAL.
        hWnd := isTaskModal
                                ifTrue: [0]
                                ifFalse:
                                        [anExternalHandle
                                                ifNil: [UserLibrary default getActiveWindow ifNil: [UserLibrary
default getDesktopWindow]]].

... <methods remains skipped> ...

D. Zamotkin


Reply | Threaded
Open this post in threaded view
|

Re: Bug in UserLibrary>>messageBox:text:caption:style:icon:instance:

Blair McGlashan-4
"Dmitry Zamotkin" <[hidden email]> wrote in message
news:[hidden email]...

> Cyclic errors are appeared when there are no active application window
> yet. Parent window handle should points to desktop:
>
> messageBox: anExternalHandle text: textString caption: captionString
> style: styleInteger icon: iconIdentifier instance: hInstance
> | iconId struct wasDisabled hWnd response isTaskModal |
> isTaskModal := styleInteger allMask: MB_TASKMODAL.
> hWnd := isTaskModal
> ifTrue: [0]
> ifFalse:
> [anExternalHandle
> ifNil: [UserLibrary default getActiveWindow ifNil: [UserLibrary
> default getDesktopWindow]]].
>
> ... <methods remains skipped> ...

Yes, this is a known problem "2107:
UserLibrary>>messageBox:text:caption:style:icon:instance: fails if there are
no open windows", first reported by Steve Waring & Ted Bracht. Sorry you've
been bitten by it.

It will be fixed in 6.03, in the meantime patch below.

Regards

Blair

-----------------
!UserLibrary methodsFor!

messageBox: anExternalHandle text: textString caption: captionString style:
styleInteger icon: iconIdentifier instance: hInstance
 | iconId struct wasDisabled hWnd response isTaskModal |
 isTaskModal := styleInteger allMask: MB_TASKMODAL.
 hWnd := isTaskModal
    ifTrue: [0]
    ifFalse:
     ["#2107: getActiveWindow may return nil, e.g. in a headless app with no
windows"
     anExternalHandle ifNil: [UserLibrary default getActiveWindow ifNil:
[0]]].
 struct := MSGBOXPARAMS new.
 struct dwStyle: styleInteger.
 struct lpszText: textString.
 struct lpszCaption: captionString.
 iconId := iconIdentifier.
 iconId isNil
  ifFalse:
   ["#1633: On NT systems if the icon has a string resource identifier it
must
   be passed as a Unicode string even though we are calling the ANSI version
of
   the MessageBoxIndirect() function!!. This is obviously a Windows bug
which we
   need to work around."
   (iconId isInteger not and: [OSVERSIONINFO current isNT]) ifTrue: [iconId
:= iconId asUnicodeString].
   struct lpszIcon: iconId asDword.
   hInstance notNil ifTrue: [struct hInstance: hInstance asParameter]].
 struct hwndOwner: hWnd.
 isTaskModal
  ifTrue:
   ["If taskModal, then the owner will be the desktop so we need to get
actual active view"
   hWnd := self getActiveWindow.
   "Ensure owner is (temporarily) enabled to prevent losing activation when
box is closed"
   (wasDisabled := (self isWindowEnabled: hWnd) not) ifTrue: [self
enableWindow: hWnd bEnable: true].
   response :=
     [SessionManager inputState startIdleTimer: hWnd.
     "Task modal only disables windows in the calling thread, so we can't
use an
     overlapped call here."
     self messageBoxIndirect: struct]
       ensure: [SessionManager inputState stopIdleTimer: hWnd]]
  ifFalse:
   [wasDisabled := (self isWindowEnabled: hWnd) not.
   "MessageBoxIndirect is called using an overlapped call on a separate
thread to avoid
   losing control of the message loop. If the initiating process is the UI
process then its
   priority is boosted so that the operation requested by the user completes
more quickly
   when the dialog is closed."
   Processor forkMainIfMain
    ifTrue:
     [| proc |
     proc := Processor activeProcess.
     proc priority: proc priority + 1].
   response := self overlappedMsgBoxIndirect: struct].

 "The message box will unhelpfully re-enable the window regardless of
whether previously disabled"
 wasDisabled ifTrue: [self enableWindow: hWnd bEnable: false].
 response == 0 ifTrue: [self systemError].
 ^response! !
!UserLibrary categoriesFor:
#messageBox:text:caption:style:icon:instance:!displaying!private! !