Удалите рамку/окно/границу другой программы (бит Aero) с помощью VB.NET

Есть ли способ удалить границу/рамку (бит Aero) окна другого приложения (скажем, блокнота) из программы VB.NET?


person Jonathan.    schedule 15.02.2010    source источник
comment
Вы имеете в виду, что хотите изменить тип границы или вообще удалить границу?   -  person Zach Johnson    schedule 18.02.2010


Ответы (1)


Вы можете сделать это с помощью P-Invoke. Ниже приведен код, в котором используется SetWindowLong (в User32.dll), чтобы изменить границу главного окна блокнота. (Этот код предполагает, что у вас запущен блокнот.) Вы можете поэкспериментировать с различными стилями окон, чтобы добиться желаемого результата.

GWL_STYLE предназначен для основных стилей окон. Вы можете прочитать о них здесь.
GWL_EXSTYLE предназначен для расширенных стилей окон. Вы можете прочитать о них здесь.

Imports System.Diagnostics
Imports System.Runtime.InteropServices

Module Module1

    Sub Main()
       Dim notepad As Process = Process.GetProcessesByName("notepad")(0)

       Dim GWL_STYLE As Int32 = -16
       Dim GWL_EXSTYLE As Int32 = -20

       ' MainWindowHandle happens to be the handle of the window you want for notepad.

       ' It may not be the handle you want if you try this on a different process.

       Dim hWnd As IntPtr = notepad.MainWindowHandle

       ' You can examine the current styles using GetWindowLong.
       Dim styles As WindowStyles = GetWindowLong(hWnd, GWL_STYLE)
       Dim exStyles As WindowStyles = GetWindowLong(hWnd, GWL_EXSTYLE)

       ' WS_VISIBLE must be used for the window to be selectable.
       Dim newStyles As WindowStyles = WindowStyles.WS_VISIBLE Or WindowStyles.WS_BORDER

       SetWindowLong(hWnd, GWL_STYLE, newStyles)

       ' If you want to modify the extended styles, use GWL_EXSTYLE

       SetWindowLong(hWnd, GWL_EXSTYLE, exStyles)


    End Sub

     _
 Private Function GetWindowLong( _
      ByVal hWnd As IntPtr, _
      ByVal nIndex As Integer) As Integer
    End Function

     _
    Private Function SetWindowLong( _
    ByVal hWnd As IntPtr, _
    ByVal nIndex As Integer, _
    ByVal dwNewLong As IntPtr) As Integer
    End Function

End Module

 _
Public Enum WindowStyles As Long

    WS_OVERLAPPED = 0
    WS_POPUP = 2147483648
    WS_CHILD = 1073741824
    WS_MINIMIZE = 536870912
    WS_VISIBLE = 268435456
    WS_DISABLED = 134217728
    WS_CLIPSIBLINGS = 67108864
    WS_CLIPCHILDREN = 33554432
    WS_MAXIMIZE = 16777216
    WS_BORDER = 8388608
    WS_DLGFRAME = 4194304
    WS_VSCROLL = 2097152
    WS_HSCROLL = 1048576
    WS_SYSMENU = 524288
    WS_THICKFRAME = 262144
    WS_GROUP = 131072
    WS_TABSTOP = 65536

    WS_MINIMIZEBOX = 131072
    WS_MAXIMIZEBOX = 65536

    WS_CAPTION = WS_BORDER Or WS_DLGFRAME
    WS_TILED = WS_OVERLAPPED
    WS_ICONIC = WS_MINIMIZE
    WS_SIZEBOX = WS_THICKFRAME
    WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW

    WS_OVERLAPPEDWINDOW = WS_OVERLAPPED Or WS_CAPTION Or WS_SYSMENU Or _
              WS_THICKFRAME Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX
    WS_POPUPWINDOW = WS_POPUP Or WS_BORDER Or WS_SYSMENU
    WS_CHILDWINDOW = WS_CHILD

    WS_EX_DLGMODALFRAME = 1
    WS_EX_NOPARENTNOTIFY = 4
    WS_EX_TOPMOST = 8
    WS_EX_ACCEPTFILES = 16
    WS_EX_TRANSPARENT = 32

    '#If (WINVER >= 400) Then
    WS_EX_MDICHILD = 64
    WS_EX_TOOLWINDOW = 128
    WS_EX_WINDOWEDGE = 256
    WS_EX_CLIENTEDGE = 512
    WS_EX_CONTEXTHELP = 1024

    WS_EX_RIGHT = 4096
    WS_EX_LEFT = 0
    WS_EX_RTLREADING = 8192
    WS_EX_LTRREADING = 0
    WS_EX_LEFTSCROLLBAR = 16384
    WS_EX_RIGHTSCROLLBAR = 0

    WS_EX_CONTROLPARENT = 65536
    WS_EX_STATICEDGE = 131072
    WS_EX_APPWINDOW = 262144

    WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE Or WS_EX_CLIENTEDGE
    WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE Or WS_EX_TOOLWINDOW Or WS_EX_TOPMOST
    '#End If

    '#If (WIN32WINNT >= 500) Then
    WS_EX_LAYERED = 524288
    '#End If

    '#If (WINVER >= 500) Then
    WS_EX_NOINHERITLAYOUT = 1048576 ' Disable inheritence of mirroring by children
    WS_EX_LAYOUTRTL = 4194304 ' Right to left mirroring
    '#End If

    '#If (WIN32WINNT >= 500) Then
    WS_EX_COMPOSITED = 33554432
    WS_EX_NOACTIVATE = 67108864
    '#End If

End Enum

Пояснение кода

Я не уверен, сколько у вас опыта в разработке приложений с графическим интерфейсом, поэтому я расскажу немного о том, как работает окно. Окно имеет уникальный идентификационный номер, называемый дескриптором. Также с окном связана оконная процедура, которая обрабатывает сообщения (целые числа, идентифицирующие события и команды) для этого окна. Когда окно создано, вы указываете, какие стили вы хотите использовать для окна и т. д. Windows-приложения намного сложнее, но чтобы не увязнуть в деталях, мы продолжим.

К счастью, .NET Winforms изолирует нас от необходимости взаимодействовать с Windows API и напрямую обрабатывать сообщения (по большей части) и позволяет очень легко создавать функциональные приложения с графическим интерфейсом. Под капотом Windows API гораздо больше возможностей, о которых большинству разработчиков .NET обычно не нужно беспокоиться.

Теперь с этим фоном код должен быть немного легче для понимания.

Во-первых, нам нужно получить первый процесс с именем «блокнот».

Dim notepad As Process = Process.GetProcessesByName("notepad")(0)

Затем мы определяем два целых числа GWL_STYLE и GWL_EXSTYLE. Эти два целых числа будут иметь особое значение в контексте функции SetWindowLong. Их значение (и значение многих других констант) можно найти в Winuser.h и остальных файлах заголовков в Windows SDK.

Dim GWL_STYLE As Int32 = -16
Dim GWL_EXSTYLE As Int32 = -20

Далее мы получаем дескриптор главного окна блокнота.

Dim hWnd As IntPtr = notepad.MainWindowHandle

После этого мы сталкиваемся с функцией GetWindowLong. Из MSDN:

Функция GetWindowLong извлекает информацию об указанном окне.

GetWindowLong принимает дескриптор окна и значение, указывающее, какую информацию нужно получить, и возвращает указанную информацию.

Dim styles As WindowStyles = GetWindowLong(hWnd, GWL_STYLE)
Dim exStyles As WindowStyles = GetWindowLong(hWnd, GWL_EXSTYLE)

Они были включены, чтобы вы могли видеть, какие стили были применены к окну, чтобы вы могли определить, какие стили следует исключить.

Далее мы определяем, какие стили мы хотим применить к окну. Вы можете прочитать о различных стилях и их значениях здесь.

Dim newStyles As WindowStyles = WindowStyles.WS_VISIBLE Or WindowStyles.WS_BORDER

Затем мы применяем эти стили к окну, используя SetWindowLong. Из MSDN:

Функция SetWindowLong изменяет атрибут указанного окна.

SetWindowLong принимает дескриптор окна, значение, указывающее, какой атрибут следует изменить, новое значение атрибута и изменяет атрибут.

SetWindowLong(hWnd, GWL_STYLE, newStyles)

Это в основном то, что делает код. Чтобы не повторяться, я не буду останавливаться на GWL_EXSTYLE, так как он используется точно так же, как GWL_STYLE. Остальной код — это просто логистика, позволяющая нам использовать SetWindowLong и GetWindowLong.

person Zach Johnson    schedule 17.02.2010
comment
хорошо, я понятия не имею, что означает этот код, поэтому, если бы вы могли просмотреть его построчно, но он работает, поэтому я принял его как ответ - person Jonathan.; 21.02.2010
comment
Большое спасибо! Одна вещь, которую я не понимаю, почему для NewStyle установлено значение WS_Visible ИЛИ WS_Border? почему это или? - person Jonathan.; 22.02.2010
comment
@Джонатан. Это оператор побитового ИЛИ. (msdn.microsoft.com/en-us/library /wz3k228a%28VS.80%29.aspx) Он объединяет установленные биты двух чисел. Например: выполнение побитового ИЛИ на 00000110 и 00000001 приводит к 00000111. Использование побитового ИЛИ позволяет представить несколько логических значений в одном целом числе (0-бит - ложь, 1-бит - истина). Таким образом, WS_Visible OR WS_Border на самом деле означает WS_Visible в сочетании с WS_Border. - person Zach Johnson; 22.02.2010
comment
@Jonathan: Что ж, «И», возможно, имело бы больше смысла с лингвистической точки зрения, но побитовое И фактически возвращает значение, в котором биты установлены как для первого, так и для второго числа (отсюда и название «И»). Например: выполнение побитового И на 00000001 и 00000111 приводит к результату 00000001. Побитовое И полезно для проверки того, установлен ли битовый «флаг», но не объединяет «установленные» биты, как это делает побитовое ИЛИ. - person Zach Johnson; 22.02.2010