Making an XL Common Dialog Modeless ?

Jaafar Tribak

Well-known Member
Joined
Dec 5, 2002
Messages
9,589
Office Version
  1. 2016
Platform
  1. Windows
I wonder if this is even possible but wouldn't it be nice to have, let's say, the Cell Formatting Dialog on display while still being able to scroll the worksheet and format the cells all over without having to select them first. Something similar to the behaviour of the Find dialog window .

I've been messing around with some code but with no luck. Has anyone seen this done before ?

Regards.
 

Excel Facts

Difference between two dates
Secret function! Use =DATEDIF(A2,B2,"Y")&" years"&=DATEDIF(A2,B2,"YM")&" months"&=DATEDIF(A2,B2,"MD")&" days"
I managed to make the Cell Formatting dialog window look Modeless but i can't find a way to set the keyboard focus back to the main XL window when clicking on the worksheet.

The mouse focus works fine .ie - you can select worksheet cells etc while the dialog is on display.

I have tried changing the Windows Styles of the dialog window as well as trapping all the Window messages directed to it and to that of the XL app through subclassing both windows.

I have even looked into intrinsic dialog related Msgs as well as tried using SetActiveWindow, SetForeGroundWindow, SendMessage WM_SETFOCUS .. etc to put the keyboard focus back on the worksheet but to no avail .

Here is what i have so far :
http://www.datafilehost.com/download-e3d51d5f.html

code in a standard module:

Code:
'Option Explicit
 
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 EnableWindow Lib "user32" _
(ByVal hwnd As Long, ByVal fEnable As Long) As Long
 
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 CallNextHookEx Lib "user32" _
(ByVal hHook As Long, ByVal ncode As Long, _
ByVal wParam As Long, lParam As Any) As Long
 
 
Private Declare Function GetClassName _
Lib "user32" Alias "GetClassNameA" _
(ByVal hwnd As Long, ByVal lpClassName As String, _
ByVal nMaxCount As Long) As Long
 
Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
 
Private Declare Function CallWindowProc Lib "user32" _
Alias "CallWindowProcA" _
(ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, _
ByVal Msg As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long
 
Private Declare Function SetFocus Lib "user32" (ByVal hwnd As Long) As Long
 
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Integer, ByVal Source As Long, ByVal Length As Long)
Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
 
Private Const WA_ACTIVE As Long = 1
Private Const WA_INACTIVE As Long = 0
Private Const GWL_WNDPROC = -4
Private Const WM_INITDIALOG As Long = &H110
Private Const WM_ACTIVATE = &H6
Private Const WH_CBT As Long = 5
Private Const HCBT_ACTIVATE = 5
Private lPrevWnd As Long
Private lhHook As Long
Private bHookEnabled As Boolean

Sub StartHook()
 
    'install a cbt hook to monitor for the activation of a window
    If Not bHookEnabled Then
        lhHook = SetWindowsHookEx _
        (WH_CBT, AddressOf HookProc, 0, GetCurrentThreadId)
        bHookEnabled = True
    Else
        MsgBox "The Event is already active.", vbInformation
    End If
 
End Sub
 
Sub TerminateHook()
 
    'important to unhook when done!
    UnhookWindowsHookEx lhHook
    bHookEnabled = False
 
End Sub
 
Private Function HookProc _
(ByVal idHook As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
 
    Dim sBuffer1 As String
    Dim lRetVal As Long
    
    'check if a window has been activated.
    If idHook = HCBT_ACTIVATE Then
    
        'if so,get it's class name.
        sBuffer1 = Space(256)
        lRetVal = GetClassName(wParam, sBuffer1, 256)
        
        'check if it is a "bosa_sdm_XL9" window that is being activated
        If Left(sBuffer1, lRetVal) = "bosa_sdm_XL9" Then
        
            'make the 'Cell Formatting ' Dialog Modeless
            'by enabling the main XL app window.
            EnableWindow GetParent(wParam), 1
            
            'subclass the 'Cell Formatting ' Dialog to intercept its Msgs.
            lPrevWnd = SetWindowLong _
            (wParam, GWL_WNDPROC, AddressOf CallBackProc)
            
            'remove CBT hook
            Call TerminateHook
        
        End If
    
    End If
    
    'Call next hook
    HookProc = CallNextHookEx(lhHook, idHook, ByVal wParam, ByVal lParam)
 
End Function

Private Function CallBackProc(ByVal hwnd As Long, ByVal Msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
 
    On Error Resume Next
    
    If Msg = WM_ACTIVATE Then
    
        Select Case True
            'if user activates the main XL app window
            'set the keyboard focus back to XL
            Case LOWORD(wParam) = WA_INACTIVE
        
                SetFocus Application.hwnd '***** NOT WORKING !!!! *****
        
            Case LOWORD(wParam) = WA_CLICKACTIVE Or _
            LOWORD(wParam) = WA_ACTIVE
        
       End Select
    
    End If
    
    CallBackProc = CallWindowProc(lPrevWnd, hwnd, Msg, wParam, ByVal lParam)
 
End Function
 
Private Function LOWORD(dw As Long) As Integer
 
    CopyMemory LOWORD, VarPtr(dw), 2
    
End Function

I hope someone with some expertise on this can figure out what is wrong with code .

Regards.
 
Upvote 0
Jaafar,
Given that there isn't an Apply button on the dialog, can I ask what you hope to gain from this? :)
 
Upvote 0
Thanks for responding rorya .

Jaafar,
Given that there isn't an Apply button on the dialog, can I ask what you hope to gain from this? :)

I guess I can manage the "apply button" bit either by subclassing the built-in OK Button or by creating a new one and embeeding it into the dialog.

At this stage, the most difficult part to achieve is setting the keyboard focus back to the worksheet when a cell is selected.If I solve this, the rest ,i hope, will be relatively easier.

Ultimately, my goal from all this is to figure out if a Modal windows common dialog can be converted to a Modeless one at run time. If that can be done then it can be applied to various other scenarios and ,i believe, we will have gained a lot in terms of functionaly and above all in terms of learning some interesting underlying workings of the Win32 interface.

Regards.
 
Upvote 0
Does it help if you use EnableWindow on the workbook window specifically, rather than the application one, as a matter of interest?
 
Upvote 0
Does it help if you use EnableWindow on the workbook window specifically, rather than the application one, as a matter of interest?

I've tried that by getting the hwnd to the "EXCEL7" window Class but it didn't work either.

I've googled for this topic but found nothing except some ugly code written in the C language which I couldn't adapt to VB.

Regards.
 
Upvote 0

Forum statistics

Threads
1,214,387
Messages
6,119,222
Members
448,877
Latest member
gb24

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top