Inter-related Windows !!

Hi all,

I want to have a NotePad application stick to my form so if I move the form, the Notepad app will move with it and if I minimise the form it will also minimise.

I am not sure what Window Style I should set for the notepad to behave like that.

I have tried WS_CHILD but didn't really work.

Anybody on this one.

Thank you.
RAFAAJAsked:
Who is Participating?
 
Mike TomlinsonConnect With a Mentor Middle School Assistant TeacherCommented:
Here is how to disable the X (close button) in the top right and also how to remove the File --> Exit item in the menu system for Notepad.

Option Explicit

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

Private Declare Function DrawMenuBar Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetMenuItemCount Lib "user32" (ByVal hMenu As Long) As Long
Private Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Long, ByVal bRevert As Long) As Long
Private Declare Function RemoveMenu Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long
 
Private Declare Function GetMenu Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetSubMenu Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long
 
Private Const MF_BYPOSITION = &H400
Private Const MF_REMOVE = &H1000
 
Private Sub Command1_Click()
    Dim noteWnd As Long
    noteWnd = FindWindow("Notepad", vbNullString)
    If noteWnd <> 0 Then
        DisableX noteWnd
        RemoveNotepadFileExit noteWnd
    End If
End Sub

Private Sub DisableX(ByVal hwnd As Long)
    Dim hMenu As Long
    Dim lItemCount As Long
    hMenu = GetSystemMenu(hwnd, 0)
    If hMenu Then
        lItemCount = GetMenuItemCount(hMenu)
        Call RemoveMenu(hMenu, lItemCount - 1, MF_REMOVE Or MF_BYPOSITION)
        Call RemoveMenu(hMenu, lItemCount - 2, MF_REMOVE Or MF_BYPOSITION)
        Call DrawMenuBar(hwnd)
    End If
End Sub

Private Sub RemoveNotepadFileExit(ByVal hwnd As Long)
    Dim hMenu As Long
    hMenu = GetMenu(hwnd)
    If hMenu Then
        Dim hSubMenu As Long
        hSubMenu = GetSubMenu(hMenu, 0)
        If hSubMenu Then
            Call RemoveMenu(hSubMenu, 8, MF_REMOVE Or MF_BYPOSITION) ' Exit
            Call RemoveMenu(hSubMenu, 7, MF_REMOVE Or MF_BYPOSITION) ' Seperator
            Call DrawMenuBar(hwnd)
        End If
    End If
End Sub
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
It would be similar to the code here:
http://www.experts-exchange.com/Programming/Programming_Languages/Visual_Basic/Q_21205433.html

But instead of moving Form2, you would move your NotePad window using the SetWindowPos() API.
0
 
RAFAAJAuthor Commented:
Thanks Idle_Mind,

I can't seem to Subclass NotPad !! It's very strange !!

I can subclass other application windows but not NotePad !!!

Here is what I have in the Form_Load event. ( Notice the lPrevProc which returns 0 indicating that Subclassing has failed !)


'in the Form Module

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) 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 SetWindowLong Lib "user32" Alias "SetWindowLongA" _
    (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Private Const GWL_WNDPROC As Long = (-4)
Private Const WM_MOVING = &H216
Private Const WM_SIZING = &H214

Private lngHwnd As Long
Private lPrevProc As Long



Private Sub UserForm_Initialize()

    Shell "NOTEPAD.EXE", 1
   
    lngHwnd = FindWindow("NotePad", vbNullString)
   
    MsgBox lngHwnd   ' \\ this returns a valid Hwnd #
   
     lPrevProc = SetWindowLong(lngHwnd, GWL_WNDPROC, AddressOf HookProc)
   
    MsgBox lPrevProc   ' \\ this returns 0 !! meaning Subclassing failed !! Why ??!!!


End Sub


The HookProc resides in a Basic Module .


Can you spot what I might be doing wrong ?!! or are some applications impossible to subclass ?!

Thanks.
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
Mike TomlinsonMiddle School Assistant TeacherCommented:
Don't subclass NotePad.  VB can't subclass forms in an external application.

Subclass the VB form instead.

Then when it receives the WM_MOVING or WM_SIZING msgs, move the NotePad window accordingly using SetWindowPos() or another window moving/positioning API.
0
 
RAFAAJAuthor Commented:
Oops !  That is True ...I knew that but I somehow forgot !

Basically, what I need to do is prevent the NotePad application to be close by the user while the Form is open.

I thought about subclassing NotePad but as you said that Can't be done because it is in a foreign Process,

An alternative will probably be to change the relevant NotePad Window Styles so it can't be closed while the form is loaded  and restore it defaults upon closing the Form.

Can you think of a better alternative  for achieving the above ?

Thanks for your help.

0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
Pretty sure you can't undo these changes though so you would need to close Notepad yourself using SendMessage():

Option Explicit

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) 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 Const WM_CLOSE = &H10

Private Sub Command1_Click()
    Dim noteWnd As Long
    noteWnd = FindWindow("Notepad", vbNullString)
    If noteWnd <> 0 Then
        SendMessage noteWnd, WM_CLOSE, 0, 0
    End If
End Sub

0
 
RAFAAJAuthor Commented:
Thanks very much for following up.

Disabling the X Button and the File Exit is probably the way to go .

Again thanks for your patience with this.
0
 
zzzzzoocCommented:
Just to add to this...

You can add/remove the system menu-items via their IDs (system commands) such as SC_CLOSE for the "Close" item. To restore them, you can manually add the menu-item(s) back with the proper SC_* ID or just call GetSystemMenu() with bRevert as True to restore it.


Form1:
----------------
Option Explicit

Private Type MENUITEMINFO
    cbSize As Long
    fMask As Long
    fType As Long
    fState As Long
    wID As Long
    hSubMenu As Long
    hbmpChecked As Long
    hbmpUnchecked As Long
    dwItemData As Long
    dwTypeData As String
    cch As Long
End Type

Private Declare Function GetSystemMenu Lib "user32" (ByVal hWnd As Long, ByVal bRevert As Long) As Long
Private Declare Function InsertMenuItem Lib "user32" Alias "InsertMenuItemA" (ByVal hMenu As Long, ByVal un As Long, ByVal bool As Boolean, ByRef lpcMenuItemInfo As MENUITEMINFO) As Long
Private Declare Function DrawMenuBar Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function DeleteMenu Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long

Private Const MF_BYCOMMAND = &H0&
Private Const MFT_SEPARATOR = &H800
Private Const MFT_STRING = &H0
Private Const MIIM_STATE = &H1
Private Const MIIM_ID = &H2
Private Const MIIM_STRING = &H40
Private Const MIIM_FTYPE = &H100
Private Const SC_CLOSE = &HF060&
Private Sub Form_Load()
    '
End Sub
Private Sub Command1_Click()
    Dim hMenu As Long
    hMenu = GetSystemMenu(Me.hWnd, False)
    If (DeleteMenu(hMenu, SC_CLOSE, MF_BYCOMMAND) <> 0) Then
        Call DrawMenuBar(Me.hWnd)
        Call MsgBox("Menu deleted.")
    End If
End Sub
Private Sub Command2_Click()
    Call GetSystemMenu(Me.hWnd, True)
    Call DrawMenuBar(Me.hWnd)
   
    'Manually add the menu item...
    '
    'Dim hMenu As Long
    'Dim tMII As MENUITEMINFO
    'hMenu = GetSystemMenu(Me.hWnd, False)
    'With tMII
    '    .cbSize = Len(tMII)
    '    .dwTypeData = "Close" & vbNullChar
    '    .cch = Len(tMII.dwTypeData)
    '    .fMask = MIIM_STATE Or MIIM_ID Or MIIM_STRING Or MIIM_FTYPE
    '    .fType = MFT_STRING
    '    .wID = SC_CLOSE
    'End With
    'If (InsertMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND, tMII) <> 0) Then
    '    Call DrawMenuBar(Me.hWnd)
    '    Call MsgBox("Menu added.")
    'End If
End Sub
0
All Courses

From novice to tech pro — start learning today.