Solved

Inter-related Windows !!

Posted on 2006-06-23
8
328 Views
Last Modified: 2010-04-07
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.
0
Comment
Question by:RAFAAJ
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
8 Comments
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 16969221
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
 

Author Comment

by:RAFAAJ
ID: 16971093
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
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 16971125
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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:RAFAAJ
ID: 16971287
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
 
LVL 86

Accepted Solution

by:
Mike Tomlinson earned 125 total points
ID: 16971602
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
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 16971672
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
 

Author Comment

by:RAFAAJ
ID: 16972158
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
 
LVL 17

Expert Comment

by:zzzzzooc
ID: 16982364
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

Featured Post

Ready to get started with anonymous questions?

It's easy! Check out this step-by-step guide for asking an anonymous question on Experts Exchange.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: Martin
Here are a few simple, working, games that you can use as-is or as the basis for your own games. Tic-Tac-Toe This is one of the simplest of all games.   The game allows for a choice of who goes first and keeps track of the number of wins for…
Background What I'm presenting in this article is the result of 2 conditions in my work area: We have a SQL Server production environment but no development or test environment; andWe have an MS Access front end using tables in SQL Server but we a…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
Suggested Courses
Course of the Month4 days, 13 hours left to enroll

636 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question