ANDLL писал(а):Рисуем прозрачное окно поверх кнопки пуск и отрабатываем нажатие на него...
Dim lButton As Long, lAllProg As Long, lhwnd As Long
Private Sub Form_Load()
Dim str As String
lhwnd = FINDWINDOW("DV2ControlHost", vbNullString)
lAllProg = FindWindowEx(lhwnd, 0&, "Desktop More Programs Pane", vbNullString)
lButton = FindWindowEx(lAllProg, 0&, "Button", vbNullString)
Debug.Print GetWndText(lButton)
OldProc = GetWindowLong(lButton, GWL_WNDPROC)
SetWindowLong lButton, GWL_WNDPROC, AddressOf WndProc
End Sub
Chris писал(а):Microsoft certainly does not recommend disabling the Windows Start button,
but it can be done. The most obvious problem in doing this is that if your
application terminates unexpectedly, it will leave the Start button
disabled. It also works against the intention of the Windows design to
allow users access to the Start menu. However, if this is important for you
application, the best way to do this is to use a DLL written in VC++ that
uses a System wide, or thread specific message hook to capture the messages
that will bring up the Start menu. In fact, you cannot do this from a VB
DLL. The best we can do from VB is to disable the button itself, but this
will not prevent the Windows button or the shortcut keys from working. That
is why you need the hook. So, you can use FindWindow to find the Taskbar,
then use EnumChildWindows to find the Start button and EnableWindow to
disable it. Disabling it makes the Start button an ugly gray button, but it
will keep users from clicking on it. So you can use code like this in your
form:
Private Sub Form_Load()
Dim WinClass As String
Dim TaskBarHwnd As Long, lRet As Long, lParam As Long
WinClass = "Shell_TrayWnd"
TaskBarHwnd = FindWindow(WinClass, vbNullString)
If TaskBarHwnd = 0 Then
MsgBox "Could not find the Taskbar!"
Exit Sub
End If
lRet = EnumChildWindows(TaskBarHwnd, AddressOf EnumChildProc, lParam)
End Sub
Private Sub Form_Unload(Cancel As Integer)
Dim RetVal As Long
If StartButtonhWnd <> 0 Then
RetVal = EnableWindow(StartButtonhWnd, True)
End If
End Sub
You will also need code like this in a Module:
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Public Declare Function EnableWindow Lib "user32" _
(ByVal hwnd As Long, ByVal fEnable As Long) As Long
Public Declare Function EnumChildWindows Lib "user32" _
(ByVal hWndParent As Long, ByVal lpEnumFunc As Long, _
ByVal lParam As Long) As Long
Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _
(ByVal hwnd As Long, ByVal lpClassName As String, _
ByVal nMaxCount As Long) As Long
Public StartButtonhWnd As Long
Function EnumChildProc(ByVal lhWnd As Long, ByVal lParam As Long) _
As Long
Dim RetVal As Long
Dim WinClassBuf As String * 255
Dim WinClass As String
RetVal = GetClassName(lhWnd, WinClassBuf, 255)
WinClass = StripNulls(WinClassBuf) ' remove extra Nulls & spaces
If WinClass = "Button" Then
StartButtonhWnd = lhWnd
RetVal = EnableWindow(StartButtonhWnd, False)
EnumChildProc = False ' Stop looking
Else
EnumChildProc = True ' Keep looking
End If
End Function
Public Function StripNulls(OriginalStr As String) As String
' This removes the extra Nulls so String comparisons will work
If (InStr(OriginalStr, Chr(0)) > 0) Then
OriginalStr = Left(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)
End If
StripNulls = OriginalStr
End Function
While this will disable the Start button when the form loads and enable it
again when the from unloads, it does not prevent the user from bringing up
the Start menu using the keyboard. This is why you need the VC++ DLL. This
would need to set a WH_GETMESSAGE hook to capture the WM_SYSCOMMAND
message. Then it needs to take a look at the wParam of that message. If it
is equal to SC_TASKLIST, then it must not pass that message on to the
intended receiver. Again, the hook must either be a system-wide hook or a
thread-specific hook on the thread that would receive that message. You can
get this thread by calling GetWindowThreadProcessId on the hwnd of the
SHELL_TRAYWND (or the desktop).
You may also want to consider having your form cover the Taskbar. Here are
some Knowledge Base articles you may want to read:
Q197585 - HOWTO: Cover the Taskbar with a Window in Visual Basic
Q183009 - HOWTO: Enumerate Windows Using the WIN32 API
gaidar писал(а):На счет сабклассинга окошек других процессов вы, ребята, не совсем правы. Это можно сделать, если внедрить свой DLL файл в адресное пространство другого процесса,
gaidar писал(а):Если не ошибаюсь, то зафигачить в процесс свой DLL можн офункцией CreateRemoteThread.
Если не ошибусь, то только с помощью WriteProcessMemory.gaidar писал(а):Если не ошибаюсь, то зафигачить в процесс свой DLL можн офункцией CreateRemoteThread.
tyomitch писал(а):gaidar писал(а):На счет сабклассинга окошек других процессов вы, ребята, не совсем правы. Это можно сделать, если внедрить свой DLL файл в адресное пространство другого процесса,
Это назвается "хук". О чём и речь.
tyomitch писал(а):gaidar писал(а):Если не ошибаюсь, то зафигачить в процесс свой DLL можн офункцией CreateRemoteThread.
Ошибаешься.
Сейчас этот форум просматривают: Google-бот, SemrushBot, Yandex-бот и гости: 14