| 通常情况下,在无边框窗体中不能设置菜单。如果在无边框窗体中设置了菜单,运行时窗体上就会出现标题栏。那么,是否在无边框窗体中就不能使用菜单了呢?答案是否定的。下面我们介绍用“借鸡下蛋”的方法在窗体中设置浮动菜单。 |
| 首先借“鸡”——再添加一个窗体,然后用这个“鸡”来下“蛋”——设置菜单。具体操作步骤如下: |
| 1.在默认名为Form1的窗体的属性窗口中设置BorderStyle值为0-vbBSNone(没有边框或与边框相关的元素)。 |
| 2.从菜单“工程/添加窗体”中添加一个窗体Form2。 |
| 3.在Form2中,单击工具栏中的“菜单编辑器”。在弹出的“菜单编辑器”窗口中,按需要设置一个顶级菜单,下设若干个菜单项(至少一个),并设置好顶级菜单及各菜单项的标题(菜单中显示的文字)和名称(程序调用所需的名称)。注意:此时其顶级菜单的“可见性”可任意设置,因为本文程序中并不需要把这个窗体显示出来(而在一般的浮动菜单中其“可见性”必须设为False)。 |
| 4.在Form1的Form_MouseUp过程中添加以下代码: |
| Private Sub Form_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single) |
| '激活Form2的浮动菜单,mnuMain为顶级菜单名称 |
| 5.在Form2的各菜单项的单击事件过程中输入有关代码。 |
| 编译并运行后,在Form1上点击右键就会弹出设定的菜单。在利用这种方法时,有两点需要注意:一是这种方法虽然多添加了一个窗体,资源略显“浪费”,但实现了编程愿望,也不枉然。而且如果程序中除主窗体外,还需要一个有标题栏的窗体(如“关于”对话框),则可以把菜单建在该窗体中(设计时,使顶级菜单不可见,当然其BorderStyle值不能为0)。这样,不但系统资源得到了充分利用,而且设想的功能也全部实现。二是在Form1窗体中,每次调用Form2的浮动菜单时,会先在窗体Form2中产生Initialize事件,再产生Load事件,然后显示浮动菜单。因此编程时,如果在Form2中含有涉及到上述两过程的代码调用,一定要加以注意。 |
| 默认情况下,无边框窗体不在任务栏中显示图标。一般情况下,要使它能在任务栏中显示,只要将其ShowInTaskbar属性设为True。但此时只有标题没有图标,而且,通常情况下的任务栏中鼠标右键的系统菜单也没有。 |
| 实际上,我们可以用API函数来解决此问题。首先将下面的代码放入窗体的声明段中: |
| 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_STYLE = (-16) |
| Private Const WS_SYSMENU = &H80000 |
| Private Const WS_SIZEBOX = &H40000 |
| Private Const WS_MAXIMIZEBOX = &H10000 |
| Private Const WS_MINIMIZEBOX = &H20000 |
| ’为任务栏添加图标和系统菜单(仅关闭和移动两个菜单项有效) |
| lStyle = lStyle Or WS_SIZEBOX |
| lStyle = lStyle Or WS_MAXIMIZEBOX |
| lStyle = lStyle Or WS_MINIMIZEBOX |
| SetWindowLong hWnd, GWL_STYLE, lStyle |
| 运行后就会发现,在任务栏中标题和图标都有了,点击右键也出现了系统菜单,并且其效果与常规的基本一致。与常规窗口不同的有两个地方:一是窗口处于活动状态时,单击不能将其最小化,但用标题栏中的菜单最小化时单击任务栏能恢复。二是“关闭”功能失效,并且当改变了窗体大小时,窗体的效果由原来的平面变为3D,这时可用鼠标调整窗体大小。 |
| 由于Form的BorderStyle属性在运行时是只读的,所以一般情况下在运行时不能改变窗体式样。但我们可以通过API函数并结合上节的相关内容来实现无边框窗体与普通窗体之间的转换,实际上是在保持BorderStyle属性不变的情况下,对标题栏进行了显示与隐藏的操作。 |
| 首先新建一个工程,在代码窗口添加以下声明和过程代码: |
| Private Declare Function SetWindowLong Lib “user32” Alias “SetWindowLongA”(ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long |
| Private Declare Function GetWindowLong Lib “user32” Alias “GetWindowLongA”(ByVal hwnd As Long, ByVal nIndex As Long) As Long |
| Private Const GWL_STYLE = (-16) |
| Private Const WS_SYSMENU = &H80000 |
| Private Const WS_CAPTION = &HC00000 |
| Private Const WS_SIZEBOX = &H40000 |
| Private Const WS_MAXIMIZEBOX = &H10000 |
| Private Const WS_MINIMIZEBOX = &H20000 |
| Private Declare Function SetWindowPos Lib “user32”(ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long |
| Private Const SWP_NOZORDER = &H4 |
| Private Const SWP_FRAMECHANGED = &H20 |
| Private Const SWP_NOREPOSITION = &H200 |
| Private Declare Function GetWindowRect Lib “user32”(ByVal hwnd As Long, lpRect As RECT) As Long |
| GetWindowRect Me.hwnd, MyRect |
| lStyle=GetWindowLong(Me.hwnd, GWL_STYLE) |
| ’分别使系统菜单(包括图标)、标题、大小、最大化、最小化显示/有效 |
| lStyle = lStyle Or WS_SYSMENU |
| lStyle = lStyle Or WS_CAPTION |
| lStyle = lStyle Or WS_SIZEBOX |
| lStyle = lStyle Or WS_MAXIMIZEBOX |
| lStyle = lStyle Or WS_MINIMIZEBOX |
| ’分别使系统菜单(包括图标)、标题、大小、最大化、最小化隐藏/无效 |
| lStyle = lStyle And Not WS_SYSMENU |
| lStyle = lStyle And Not WS_CAPTION |
| lStyle = lStyle And Not WS_SIZEBOX |
| lStyle = lStyle And Not WS_MAXIMIZEBOX |
| lStyle = lStyle And Not WS_MINIMIZEBOX |
| SetWindowLong Me.hwnd, GWL_STYLE, lStyle |
| SetWindowPos Me.hwnd, 0, MyRect.Left, MyRect.Top,MyRect.Right - MyRect.Left, |
| MyRect.Bottom - MyRect.Top,SWP_NOREPOSITION Or SWP_NOZORDER Or SWP_FRAMECHANGED |
| 这样,每次单击窗体,标题栏就会在显示和隐藏之间进行切换。 | |
|