הערה
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות להיכנס או לשנות מדריכי כתובות.
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות לשנות מדריכי כתובות.
Question
Thursday, September 3, 2020 3:38 PM
Hi everybody,
I have problem with winform application and need to help.
I create a new form, i want hide the title bar but the form can be resize and move. I try set some below attributes but when run it, it always have a whitespace at top of the form
- formborderstyle = sizable
- control box = false
- me.text = ""
How can I remove it?
Please help me, thank you very much!
All replies (11)
Thursday, September 3, 2020 3:59 PM
Hi everybody,
I have problem with winform application and need to help.
I create a new form, i want hide the title bar but the form can be resize and move. I try set some below attributes but when run it, it always have a whitespace at top of the form
- formborderstyle = sizable
- control box = false
- me.text = ""
How can I remove it?
Please help me, thank you very much!
Hi
- formborderstyle = none
Regards Les, Livingston, Scotland
Thursday, September 3, 2020 4:35 PM
Thank you Les,
I tried it before.
But I cannot resize the form by hold on the edge and move mouse when set it.
Thursday, September 3, 2020 4:39 PM
Hi
That is correct. You need to take account of that if you use the Borders = None.
You would need to work to build your own resize and relocate for the Form.
It is much easier to live with the Form Title text and what you call white space. BTW why do you want to not have the title bar at the top of the Form?
Regards Les, Livingston, Scotland
Friday, September 4, 2020 6:45 AM
I create a new form, i want hide the title bar but the form can be resize and move.
It is now done with DWM , mainly DwmExtendFrameIntoClientArea
Friday, September 4, 2020 9:41 AM
It look great! Could you share me more about how Can I do it? Ex: code example
Friday, September 4, 2020 11:06 AM | 1 vote
I adapted the MSDN C++ code from Custom Window Frame Using DWM :
Imports System.Runtime.InteropServices
' Reference : https://docs.microsoft.com/en-us/windows/win32/dwm/customframe
Public Class Form1
<StructLayout(LayoutKind.Sequential)>
Public Structure MARGINS
Public cxLeftWidth, cxRightWidth, cyTopHeight, cyBottomHeight As Integer
Public Sub New(ByVal left As Integer, ByVal right As Integer, ByVal top As Integer, ByVal bottom As Integer)
cxLeftWidth = left
cyTopHeight = top
cxRightWidth = right
cyBottomHeight = bottom
End Sub
End Structure
<DllImport("Dwmapi.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Public Shared Function DwmExtendFrameIntoClientArea(ByVal hwnd As IntPtr, ByRef margins As MARGINS) As Integer
End Function
<DllImport("Dwmapi.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Public Shared Function DwmIsCompositionEnabled(ByRef enabled As Boolean) As Integer
End Function
<DllImport("Dwmapi.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Public Shared Function DwmDefWindowProc(ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr, ByRef plResult As IntPtr) As Boolean
End Function
Public Const WM_CREATE As Integer = &H1
Public Const WM_ACTIVATE As Integer = &H6
Public Const WM_ACTIVATEAPP As Integer = &H1C
Public Const WM_NCCALCSIZE As Integer = &H83
Public Const WM_NCHITTEST As Integer = &H84
Public Const WM_NCACTIVATE As Integer = &H86
Public Const WM_RBUTTONDOWN As Integer = &H204
Public Const WM_RBUTTONUP As Integer = &H205
Public Const WM_NCLBUTTONDOWN As Integer = &HA1
Public Const WM_NCLBUTTONUP As Integer = &HA2
Public Const WM_NCRBUTTONDOWN As Integer = &HA4
Public Const WM_NCRBUTTONUP As Integer = &HA5
Public Const WS_OVERLAPPED As Integer = &H0, WS_POPUP As Integer = &H80000000, WS_CHILD As Integer = &H40000000, WS_MINIMIZE As Integer = &H20000000, WS_VISIBLE As Integer = &H10000000, WS_DISABLED As Integer = &H8000000, WS_CLIPSIBLINGS As Integer = &H4000000, WS_CLIPCHILDREN As Integer = &H2000000, WS_MAXIMIZE As Integer = &H1000000, WS_CAPTION As Integer = &HC00000, WS_BORDER As Integer = &H800000, WS_DLGFRAME As Integer = &H400000, WS_VSCROLL As Integer = &H200000, WS_HSCROLL As Integer = &H100000, WS_SYSMENU As Integer = &H80000, WS_THICKFRAME As Integer = &H40000, WS_TABSTOP As Integer = &H10000, WS_MINIMIZEBOX As Integer = &H20000, WS_MAXIMIZEBOX As Integer = &H10000
Public Const WS_OVERLAPPEDWINDOW As Integer = WS_OVERLAPPED Or WS_CAPTION Or WS_SYSMENU Or WS_THICKFRAME Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX
Public Const SWP_NOREDRAW As Integer = &H8, SWP_FRAMECHANGED As Integer = &H20, SWP_NOCOPYBITS As Integer = &H100, SWP_NOOWNERZORDER As Integer = &H200, SWP_NOSENDCHANGING As Integer = &H400, SWP_NOREPOSITION As Integer = SWP_NOOWNERZORDER, SWP_DEFERERASE As Integer = &H2000, SWP_ASYNCWINDOWPOS As Integer = &H4000
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Public Shared Function SetWindowPos(ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal x As Integer, ByVal y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal flags As Integer) As Boolean
End Function
<StructLayout(LayoutKind.Sequential)>
Public Structure RECT
Public left As Integer
Public top As Integer
Public right As Integer
Public bottom As Integer
Public Sub New(left As Integer, top As Integer, right As Integer, bottom As Integer)
Me.left = left
Me.top = top
Me.right = right
Me.bottom = bottom
End Sub
End Structure
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Public Shared Function GetWindowRect(hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
End Function
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Public Shared Function AdjustWindowRectEx(ByRef lpRect As RECT, ByVal dwStyle As Integer, ByVal bMenu As Boolean, ByVal dwExStyle As Integer) As Boolean
End Function
Public Const HTNOWHERE As Integer = 0, HTTRANSPARENT As Integer = -1, HTCAPTION As Integer = 2, HTSYSMENU As Integer = 3, HTGROWBOX As Integer = 4, HTMENU As Integer = 5,
HTHSCROLL As Integer = 6, HTVSCROLL As Integer = 7, HTMINBUTTON As Integer = 8, HTMAXBUTTON As Integer = 9, HTLEFT As Integer = 10, HTRIGHT As Integer = 11, HTTOP As Integer = 12,
HTTOPLEFT As Integer = 13, HTTOPRIGHT As Integer = 14, HTBOTTOM As Integer = 15, HTBOTTOMLEFT As Integer = 16, HTBOTTOMRIGHT As Integer = 17, HTBORDER As Integer = 18,
HTCLOSE As Integer = 20, HTHELP As Integer = 21, HTMDIMAXBUTTON As Integer = 66, HTMDIMINBUTTON As Integer = 67, HTMDICLOSE As Integer = 68
Public Structure NCCALCSIZE_PARAMS
Public rect0 As RECT
Public rect1 As RECT
Public rect2 As RECT
Public lppos As IntPtr
End Structure
Public Shared Function HIWORD(ByVal i As Integer) As Integer
Return CShort(i >> 16)
End Function
Public Shared Function LOWORD(ByVal i As Integer) As Integer
Return CShort(i And &HFFFF)
End Function
Public Shared Function GET_X_LPARAM(ByVal lParam As IntPtr) As Integer
Return LOWORD(lParam.ToInt32())
End Function
Public Shared Function GET_Y_LPARAM(ByVal lParam As IntPtr) As Integer
Return HIWORD(lParam.ToInt32())
End Function
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Public Shared Function DestroyWindow(hWnd As IntPtr) As Boolean
End Function
Private Shared windowMargins As MARGINS
Private Const TOPEXTENDWIDTH As Integer = 2
Private Const LEFTEXTENDWIDTH As Integer = 2
Private Const RIGHTEXTENDWIDTH As Integer = 2
Private Const BOTTOMEXTENDWIDTH As Integer = 2
Friend WithEvents Button1 As Button
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Button1 = New Button()
Button1.Location = New Point(350, 6)
Button1.Text = "Test Button"
Button1.BackColor = Color.Transparent
Button1.UseCompatibleTextRendering = True
Me.Controls.Add(Button1)
Me.BackColor = System.Drawing.Color.Black
CenterToScreen()
End Sub
Protected Overrides Sub WndProc(ByRef m As Message)
Dim fCallDWP As Boolean = True
Dim fDwmEnabled As Boolean = False
Dim lRet As Integer = 0
Dim hr As Integer = 0
' Winproc worker for custom frame issues.
hr = DwmIsCompositionEnabled(fDwmEnabled)
If (hr = 0) Then
lRet = CustomCaptionProc(m.HWnd, m.Msg, m.WParam, m.LParam, fCallDWP)
End If
' Winproc worker for the rest of the application.
If (fCallDWP) Then
MyBase.WndProc(m)
Else
m.Result = CType(lRet, IntPtr)
End If
End Sub
Private Shared Function CustomCaptionProc(ByVal hWnd As IntPtr, ByVal message As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr, ByRef pfCallDWP As Boolean) As Integer
Dim lRet As IntPtr = IntPtr.Zero
Dim hr As Integer = 0
Dim fCallDWP As Boolean = True
fCallDWP = Not DwmDefWindowProc(hWnd, message, wParam, lParam, lRet)
' Handle window creation.
If (message = WM_CREATE) Then
Dim rcClient As RECT = New RECT()
GetWindowRect(hWnd, rcClient)
SetWindowPos(hWnd, IntPtr.Zero, rcClient.left, rcClient.top, (rcClient.right - rcClient.left), (rcClient.bottom - rcClient.top), SWP_FRAMECHANGED)
fCallDWP = True
lRet = IntPtr.Zero
End If
'If (message = WM_ACTIVATE Or message = WM_NCACTIVATE Or message = WM_ACTIVATEAPP) Then
If (message = WM_ACTIVATE) Then
windowMargins.cxLeftWidth = LEFTEXTENDWIDTH
windowMargins.cxRightWidth = RIGHTEXTENDWIDTH
windowMargins.cyBottomHeight = BOTTOMEXTENDWIDTH
windowMargins.cyTopHeight = TOPEXTENDWIDTH
DwmExtendFrameIntoClientArea(hWnd, windowMargins)
fCallDWP = True
lRet = IntPtr.Zero
End If
' Handle the non-client size message.
If ((message = WM_NCCALCSIZE) And (wParam = CType(1, IntPtr))) Then
Dim pncsp As NCCALCSIZE_PARAMS = CType(Marshal.PtrToStructure(lParam, GetType(NCCALCSIZE_PARAMS)), NCCALCSIZE_PARAMS)
pncsp.rect0.Top = pncsp.rect0.Top + 0
pncsp.rect0.bottom = pncsp.rect0.bottom + 0
pncsp.rect0.left = pncsp.rect0.left - 0
pncsp.rect0.right = pncsp.rect0.right - 0
Marshal.StructureToPtr(pncsp, lParam, False)
' No need to pass the message on to the DefWindowProc.
lRet = IntPtr.Zero
fCallDWP = False
End If
' Handle hit testing in the NCA if not handled by DwmDefWindowProc.
If ((message = WM_NCHITTEST) And (lRet = IntPtr.Zero)) Then
lRet = HitTestNCA(hWnd, wParam, lParam)
If (lRet <> CType(HTNOWHERE, IntPtr)) Then
fCallDWP = False
End If
End If
' Close window on Right mouse button
If (message = WM_NCRBUTTONDOWN) Then
System.Threading.Thread.Sleep(200)
DestroyWindow(hWnd)
End If
pfCallDWP = fCallDWP
Return CType(lRet, Integer)
End Function
Private Shared Function HitTestNCA(ByVal hWnd As IntPtr, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
' Get the point coordinates for the hit test.
Dim ptMouse As New Point(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))
' Get the window rectangle.
Dim rcWindow As RECT = Nothing
GetWindowRect(hWnd, rcWindow)
' Get the frame rectangle, adjusted for the style without a caption.
Dim rcFrame As New RECT(0, 0, 0, 0)
AdjustWindowRectEx(rcFrame, WS_OVERLAPPEDWINDOW And Not WS_CAPTION, False, 0)
Dim uRow As UShort = 1
Dim uCol As UShort = 1
Dim fOnResizeBorder As Boolean = False
' Determine if the point is at the top or bottom of the window.
If ptMouse.Y >= rcWindow.top AndAlso ptMouse.Y < rcWindow.top + TOPEXTENDWIDTH Then
fOnResizeBorder = (ptMouse.Y < (rcWindow.top - rcFrame.top))
uRow = 0
ElseIf ptMouse.Y < rcWindow.bottom AndAlso ptMouse.Y >= rcWindow.bottom - BOTTOMEXTENDWIDTH Then
uRow = 2
End If
' Determine if the point is at the left or right of the window.
If ptMouse.X >= rcWindow.left AndAlso ptMouse.X < rcWindow.left + LEFTEXTENDWIDTH Then
uCol = 0 ' left side
ElseIf ptMouse.X < rcWindow.right AndAlso ptMouse.X >= rcWindow.right - RIGHTEXTENDWIDTH Then
uCol = 2 ' right side
End If
'Dim hitTests(,) As Integer = {
' {HTTOPLEFT, If(fOnResizeBorder, HTTOP, HTCAPTION), HTTOPRIGHT},
' {HTLEFT, HTNOWHERE, HTRIGHT},
' {HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT}
'}
Dim hitTests(,) As Integer = {
{HTTOPLEFT, If(fOnResizeBorder, HTTOP, HTCAPTION), HTTOPRIGHT},
{HTLEFT, HTCAPTION, HTRIGHT},
{HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT}
}
Return New IntPtr(hitTests(uRow, uCol))
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
MessageBox.Show("Button clicked", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
End Sub
End Class
Friday, September 4, 2020 4:32 PM
I tried it and it work well.
But have other problem: when I set window state = maximized some control nearby the edge of form will be go out of screen.
Friday, September 4, 2020 5:07 PM
I tried it and it work well.
But have other problem: when I set window state = maximized some control nearby the edge of form will be go out of screen.
You can increase borders when the window is maximized, in WM_NCCALCSIZE
For example, I add 6 to top when it is maximized :
If (IsZoomed(hWnd)) Then
pncsp.rect0.top = pncsp.rect0.top + 6
pncsp.rect0.bottom = pncsp.rect0.bottom + 0
pncsp.rect0.left = pncsp.rect0.left - 0
pncsp.rect0.right = pncsp.rect0.right - 0
Else
pncsp.rect0.top = pncsp.rect0.top + 0
pncsp.rect0.bottom = pncsp.rect0.bottom + 0
pncsp.rect0.left = pncsp.rect0.left - 0
pncsp.rect0.right = pncsp.rect0.right - 0
End If
with :
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Public Shared Function IsZoomed(hWnd As IntPtr) As Boolean
End Function
Friday, September 4, 2020 11:16 PM
That look great! Let me try it. But let me know if you have any other notices when apply this one. Because my application already have many users. We must be carefully
Saturday, September 5, 2020 9:24 AM
The border size should be calculated from Windows System Metrics
This works on my OS (Windows 10 - 1909) =>
Dim nBorderWidth = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER)
Dim nBorderHeight = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER)
If (IsZoomed(hWnd)) Then
pncsp.rect0.top = pncsp.rect0.top + nBorderHeight
pncsp.rect0.bottom = pncsp.rect0.bottom - nBorderHeight
pncsp.rect0.left = pncsp.rect0.left + nBorderWidth
pncsp.rect0.right = pncsp.rect0.right - nBorderWidth
Else
pncsp.rect0.top = pncsp.rect0.top + 0
pncsp.rect0.bottom = pncsp.rect0.bottom + 0
pncsp.rect0.left = pncsp.rect0.left - 0
pncsp.rect0.right = pncsp.rect0.right - 0
End If
with :
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Public Shared Function GetSystemMetrics(nIndex As Integer) As Integer
End Function
Public Const SM_CXDLGFRAME = 7
Public Const SM_CYDLGFRAME = 8
Public Const SM_CXFIXEDFRAME = SM_CXDLGFRAME ' ;win40 name change
Public Const SM_CYFIXEDFRAME = SM_CYDLGFRAME ' ;win40 name change
Public Const SM_CXFRAME = 32
Public Const SM_CYFRAME = 33
Public Const SM_CXPADDEDBORDER = 92
I added OnPaint to colorize the borders in Red and, when maximized, I get (left part of the window, button at (1, 1)) =>
Monday, September 14, 2020 8:54 AM
Hi Lisa Bui,
Did you solve your problem? If your question has been answered then please click the "Mark as Answer" Link at the bottom of the correct post(s), so that it will help other members to find the solution quickly if they face a similar issue.
Best Regards,
Xingyu Zhao
MSDN Community Support
Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.