如何屏蔽掉窗口右上角的关闭按钮?

 

Visual C++删除浮动工具条中“关闭”按钮


http://www.sina.com.cn 2005年07月04日 11:06 天极yesky
 

  作者: 刘涛

 

  下载本文源代码

  在Visual C++自动生成的MFC框架应用程序中,当浮动工具条被拖离主框架窗口后,一般都会在工具条的右上角有一个"关闭"按钮,应该说这个按钮完全是按照Windows应用程序的用户界面(UI)设计规范而设计的,也就是说所有的窗口都应该有一个地方让用户可以关闭这个窗口。但是有的开发人员偏偏提出来不想要这个"关闭"按钮。本实例通过自定一个扩展的工具条类,实现了删除工具条中"关闭"按钮的目的。程序编译运行后的界面效果如图一所示:

如何屏蔽掉窗口右上角的关闭按钮?_第1张图片
图一、没有"关闭"按钮的浮动工具条


  一、实现方法

  首先,针对删除工具条上"关闭"按钮的问题我们来确定一下实现的思路,因为我们要实现的功能与工具条有关,所以涉及的类肯定与 CToolBar有关。其次,为了判断工具条浮动后"关闭"按钮的状态,我们需要一个表示状态的成员变量;第三,实现工具条的浮动特性,需要对工具条窗口的ON_WM_WINDOWPOSCHANGED消息进行处理。这个消息负责CToolBar窗口大小、位置或Z坐标的变化,这里为什么不用WM_SIZE/OnSize来处理窗口大小的改变呢?因为仅当涉及窗口大小改变而不涉及窗口位置也改变时才这样调用,所以当浮动工具条时不一定每次都调用处理WM_SIZE/OnSize。我们可以利用 基类CControlBar的m_pDockBar成员变量来调用GetParent()以获取工具条的父窗口。从而改变父窗口的式样--屏蔽系统菜单,来达到我们的目的--去掉"关闭"按钮。

  有了思路,下面来看看具体的实现代码,我们先从CToolBar派生一个新类CToolBarEx,因为我们的目的是在浮动工具条时去掉"关闭"按钮,所以仅仅判断工具条是否浮动就可以了,这一点用CControlBar类的属性判断函数可以做到:BOOL IsFloating() const。在新类中添加一个成员变量,用它表示"关闭"按钮的状态:BOOL m_bMenuRemoved,当我们去掉主框架的系统菜单属性时,它的值为TRUE。接着,我们用到了 m_pDockBar,用它来判断父窗口类型是否是CMiniFrameWnd,该类代表了浮动工具条周围的框架窗口。经过上述处理后,我们就可以放心地从CToolBar中去掉系统菜单了。下面是处理ON_WM_WINDOWPOSCHANGED消息的代码:

void CToolBarEx::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos)
{
 CToolBar::OnWindowPosChanged(lpwndpos);
 // should only be called once, when floated.
 if( IsFloating() )
 {
  if( m_pDockBar && !m_bMenuRemoved )
  {
   CWnd* pParent = m_pDockBar->GetParent();
   if( pParent->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)))
   {
    pParent->ModifyStyle( WS_SYSMENU, 0, 0 );
    m_bMenuRemoved = TRUE;
   }
  }
 }
 else if( m_bMenuRemoved ) {
  m_bMenuRemoved = FALSE;
 }
}


  二、编程步骤

  1、 启动Visual C++6.0,生成一个单文档视图结构的应用程序,将程序命名为"FltTBClsBtn";

  2、 使用Class Wizard在项目中添加一个新类CtoolBarEx,其基类选择为CToolBar;

  3、 在CMainFrme类中将成员变量m_wndToolBar的类型修改为CtoolBarEx;

  4、 添加代码,编译运行程序。

三、程序代码

/
// ToolBarEx.h : header file
#ifndef __TOOLBAREX_H__
#define __TOOLBAREX_H__
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

class CToolBarEx : public CToolBar
{
 DECLARE_DYNAMIC(CToolBarEx)
 // Construction
 public:
  CToolBarEx();
  // Attributes
 protected:
  BOOL m_bMenuRemoved;
  // Operations
 public:
  // Overrides
  // ClassWizard generated virtual function overrides
  //{{AFX_VIRTUAL(CToolBarEx)
  //}}AFX_VIRTUAL
  // Implementation
 public:
  virtual ~CToolBarEx();
  // Generated message map functions
 protected:
  //{{AFX_MSG(CToolBarEx)
   afx_msg void OnWindowPosChanged(WINDOWPOS FAR* lpwndpos);
  //}}AFX_MSG
  DECLARE_MESSAGE_MAP()
};
#endif // __TOOLBAREX_H__

ToolBarEx.cpp : implementation file
#include "StdAfx.h"
#include "ToolBarEx.h"
#include
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CToolBarEx::CToolBarEx()
{
 // TODO: add construction code here.
 m_bMenuRemoved = FALSE;
}

CToolBarEx::~CToolBarEx()
{
 // TODO: add destruction code here.
}

IMPLEMENT_DYNAMIC(CToolBarEx, CToolBar)
BEGIN_MESSAGE_MAP(CToolBarEx, CToolBar)
//{{AFX_MSG_MAP(CToolBarEx)
ON_WM_WINDOWPOSCHANGED()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

// CToolBarEx message handlers

void CToolBarEx::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos)
{
 CToolBar::OnWindowPosChanged(lpwndpos);

 // should only be called once, when floated.
 if( IsFloating() )
 {
  if( m_pDockBar && !m_bMenuRemoved )
  {
   CWnd* pParent = m_pDockBar->GetParent();
   if( pParent->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)))
   {
    pParent->ModifyStyle( WS_SYSMENU, 0, 0 );
    m_bMenuRemoved = TRUE;
   }
  }
 }
 else if( m_bMenuRemoved ) {
  m_bMenuRemoved = FALSE;
 }
}

  四、小结

  本实例通过一个自定义类,处理Windows中窗口位置变化消息,实现了删除浮动工具条上"关闭"按钮的目的,在上述过程中,最主要的工作还是判断当前窗口的父窗口是否为浮动工具条的框架窗口类-CMiniFrameWnd类。
 站点首页 技术文章 源码下载 API函数手册 VBS脚本手册 站点导航 用户注册 用户登陆 论坛交流
设为主页
收藏本站
联系我们
| VB技术文章 |
 
站内搜索: 文章搜索软件搜索网站搜索   会员注册 | 会员登录      
当前位置:中国VB网→文章首页→VB技术文章→API函数→使窗体右上角的关闭按钮失效且删除系统菜单的关闭
 
使窗体右上角的关闭按钮失效且删除系统菜单的关闭
作者:不详  来源于:中国VB网  发布时间:2004-10-17

    窗体右上角的X按钮通常用来关闭一个程序,这个小X按钮实际上是和系统菜单的“关闭”菜单项关联在一起的,什么?不知道什么是系统菜单,系统菜单是指我们点击窗体左上角的小图标时所弹出的菜单,其中好象有“恢复”、“移动”、“最大化”、“最小化”、“关闭”这么几个按钮。这个菜单用普通的方法是不能编辑和改变的,但是我们可以通过API函数GetSystemMenu来得到它的句柄,然后通过菜单相关的API函数就能改变它了,下面一起看看怎么做吧。

  为了学习方便,下面先给出源码,并且已经作了详细的中文注释:

程序说明:
本例利用API函数GetSystemMenu得到系统菜单的句柄,X按钮是系统菜单的一菜单项,然后用RemoveMenu函数删去这一菜单项,也就是使X按钮失效了。
-------------------------------------------
【VB声明】

Private Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Long, ByVal bRevert As Long) As Long


【说明】
取得指定窗口的系统菜单的句柄。在vb环境,“系统菜单”的正式名称为“控制菜单”,即单击窗口左上角的控制框时出现的菜单

【返回值】
Long,如执行成功,返回系统菜单的句柄;零意味着出错。如bRevert设为TRUE,也会返回零(简单的恢复原始的系统菜单)

【备注】
在vb里使用:系统菜单会向窗口发送一条WM_SYSCOMMAND消息,而不是WM_COMMAND消息

【参数表】
hwnd ----------- Long,窗口的句柄

bRevert -------- Long,如设为TRUE,表示接收原始的系统菜单

Private Declare Function GetSystemMenu Lib "user32" ( _
ByVal hwnd As Integer, _
ByVal bRevert As Integer _
) As Integer

【VB声明】

Private Declare Function RemoveMenu Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long
【说明】
删除指定的菜单条目。如删除的条目属于一个弹出式菜单,那么这个函数不会同时删除弹出式菜单。首先应该用GetSubMenu函数取得弹出式菜单的句柄,再在以后将其删除

【返回值】
Long,非零表示成功,零表示失败。会设置GetLastError

【备注】
强烈建议大家使用vb菜单的visible属性从菜单中删除条目,而不要用这个函数,否则会造成指定菜单中其他菜单条目的visible属性对错误的菜单条目产生影响

【参数表】
hMenu ---------- Long,菜单的句柄

nPosition ------ Long,欲改变的菜单条目的标识符。如在wFlags参数中指定了MF_BYCOMMAND,这个参数就代表欲改变的菜单条目的命令ID。如设置的是MF_BYPOSITION,这个参数就代表菜单条目在菜单中的位置(第一个条目的位置为零)

wFlags --------- Long,常数MF_BYCOMMAND或MF_BYPOSITION,取决于nPosition参数

 

Private Declare Function RemoveMenu Lib "user32" ( _
ByVal hMenu As Integer, _
ByVal nPosition As Integer, _
ByVal wFlags As Integer _
) As Integer

Private Sub Command1_Click()
Unload Me
End Sub

Private Sub Form_Load()
Dim R As Integer
MyMenu = GetSystemMenu(Me.hwnd, 0)
RemoveMenu MyMenu, &HF060, R
End Sub 


  程序中用到了两个API函数GetSystemMenu、RemoveMenu,其中GetSystemMenu函数用来得到系统菜单的句柄,RemoveMenu用来删除指定的菜单条目,我们先来看看这个函数的声明和参数:

   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 
其中各GetSystemMenu参数的意义如下表:

参数 意义
hwnd Long 系统菜单所在窗口的句柄
bRevert Long 如设为TRUE,表示恢复原始的系统菜单
返回值 Long 如执行成功,返回系统菜单的句柄;零意味着出错。如bRevert设为TRUE,也会返回零(简单的恢复原始的系统菜单)

  而RemoveMenu参数的意义如下表:

参数 意义
hMenu Long 菜单的句柄
nPosition Long 欲改变的菜单条目的标识符。如在wFlags参数中指定了MF_BYCOMMAND,这个参数就代表欲改变的菜单条目的命令ID。如设置的是MF_BYPOSITION,这个参数就代表菜单条目在菜单中的位置(第一个条目的位置为零)
wFlags Long 常数MF_BYCOMMAND=&H0&或MF_BYPOSITION=&H400&,取决于nPosition参数
返回值 Long,非零表示成功,零表示失败

  然后就可以在程序中使用这两个函数了,我们在窗体的Form_Load()过程中加入如下代码:

   MyMenu = GetSystemMenu(Me.hwnd,0)    得到系统菜单的句柄,Me.hwnd表示当前窗体的句柄

   RemoveMenu MyMenu, &HF060, MF_BYCOMMAND 移去“关闭”菜单项,&HF060“关闭”菜单项的命令ID

  接着我们运行程序,看看窗体右上角的X按钮是不是已经不可点击了,系统菜单中的“关闭”项也消失了,很有趣,不过一定记着为程序留一个“退出”按钮哦!


[ 本日:1 本周:1 本月:3 总浏览数:277 ] [返回上一页] [告诉好友] [发表评论] [打 印] [ 字体:大 中 小 ]
上篇文章:调用"打开方式"窗口 
下篇文章:移动没有标题栏的窗体
∷相关文章∷
 
∷相关软件∷
 
中国VB网--全力打造中国专业VB站点!
Copyright © 2004-2005 ChinaVB.Net. All Rights Reserved . 中国VB网版权所有
投稿信箱: [email protected]
ICP证书编号: 冀ICP备05013786号

 
列表首页 >> 具体信息
主  题:  
如何屏蔽掉窗口右上角的关闭按钮?
 
     
thanks
  回复人: chinareny(编程浪子) ( ) 信誉:100 2002-05-16 10:13:28 得分:0
 
 
 
用queryunload基本上可以实现你的要求
Top
 
  回复人: chinareny(编程浪子) ( ) 信誉:100 2002-05-16 10:15:42 得分:0
 
 
 
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
If MsgBox("sure?", vbYesNo + vbDefaultButton2, "information") = vbYes Then
    Cancel = True
Else
End If
End Sub
Top
 
  回复人: lxb97251(lxb) ( ) 信誉:100 2002-05-16 10:17:25 得分:0
 
 
 
只要用一句话,经典的一句话:cancel=0 注意它不能使关闭键消失,但可以使它失效(如果不是等于0就是1)我头晕了,记不清了,自已试吧。)好用就得加分呀》我的专家分太少了。。。。不过我是新加入的。谢谢!!!!
Top
 
  回复人: mark3798(日本語を 習います) ( ) 信誉:78 2002-05-16 10:26:36 得分:0
 
 
 
搞什么呀,能不能详细点说啊,我怎么添进你的代码,怎么不可以去到关闭按钮啊!
Top
 
  回复人: mark3798(日本語を 習います) ( ) 信誉:78 2002-05-16 10:31:52 得分:0
 
 
 
不好意思,我搞定了,都有冒犯,敬请原谅!!!!
Top
 
  回复人: yclyz(秋雨) ( ) 信誉:100 2002-05-16 10:46:25 得分:0
 
 
 
bordstyple =none
复杂一点的就用API函数,不过我也不熟:(
Top
 
  回复人: xxlroad(土八路) ( ) 信誉:100 2002-05-16 10:52:53 得分:0
 
 
 
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    If MsgBox("真的要退出吗?", vbYesNo + vbQuestion, "提示") = vbYes Then
    Else
        Cancel = 1
    End If
End Sub
Top
 
  回复人: xxlroad(土八路) ( ) 信誉:100 2002-05-16 10:54:23 得分:0
 
 
 
'去除窗体中的×关闭功能
'API函数的声明。
Private Declare Function GetSystemMenu Lib "User32" (ByVal hWnd As Long, ByVal bRevert 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 Declare Function AppendMenu Lib "User32" Alias "AppendMenuA" (ByVal hMenu As Long, ByVal wFlags As Long, ByVal wIDNewItem As Long, ByVal lpNewItem As Any) As Long
Private Declare Function GetMenuString Lib "User32" Alias "GetMenuStringA" (ByVal hMenu As Long, ByVal wIDItem As Long, ByVal lpString As String, ByVal nMaxCount As Long, ByVal wFlag As Long) 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
Const WM_NCLBUTTONDBLCLK = &HA3
Const WM_NCLBUTTONDOWN = &HA1
Const HTCAPTION = 2
Const MF_STRING = &H0&
Const MF_BYCOMMAND = &H0&
Const SC_CLOSE = &HF060
'变量的声明
Private hMenu As Long
'记录Close MenuItem的字串
Private CloseStr As String
'Command1的Click事件将"关闭"的那一个MenuItem 加回来
Private Sub Command1_Click()
    Call AppendMenu(hMenu, MF_STRING, SC_CLOSE, CloseStr)
    '令"×"能出现Enable的颜色
    Call SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0&)
End Sub
'Command2的Click事件去除"关闭"菜单功能。
Private Sub Command2_Click()
    '取得系统菜单的句柄。
    hMenu = GetSystemMenu(Form1.hWnd, 0)
    CloseStr = String(255, 0)
    'SC_CLOSE指的便是"关闭"的那一个MenuItem ID
    Call GetMenuString(hMenu, SC_CLOSE, CloseStr, 256, MF_BYCOMMAND)
    '处理数据。
    CloseStr = Left(CloseStr, InStr(1, CloseStr, Chr(0)) - 1)
    '调用函数。
    Call DeleteMenu(hMenu, SC_CLOSE, MF_BYCOMMAND)
    '发送一个信息,使"×"出现Disable颜色。
    Call SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0&)
End Sub
Private Sub Form_Load()
    '初始化。
    Form1.Caption = "菜单操作"
    Command1.Caption = "恢复"
    Command2.Caption = "去除"
End Sub
Top
 
  回复人: daryl715(海军少校) ( ) 信誉:100 2002-05-16 11:11:52 得分:0
 
 
 
'****************************************************定义屏蔽关闭菜单按钮所需的API*******************************
Private Const SC_CLOSE As Long = &HF060&
Private Const MIIM_STATE As Long = &H1&
Private Const MIIM_ID As Long = &H2&
Private Const MFS_GRAYED As Long = &H3&
Private Const WM_NCACTIVATE As Long = &H86
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 GetMenuItemInfo Lib "user32" Alias _
    "GetMenuItemInfoA" (ByVal hMenu As Long, ByVal un As Long, _
    ByVal b As Boolean, lpMenuItemInfo As MENUITEMINFO) As Long
Private Declare Function SetMenuItemInfo Lib "user32" Alias _
    "SetMenuItemInfoA" (ByVal hMenu As Long, ByVal un As Long, _
    ByVal bool As Boolean, lpcMenuItemInfo As MENUITEMINFO) 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 Declare Function IsWindow Lib "user32" _
    (ByVal hwnd As Long) As Long
'*********************************************************************************************
'****************************************屏蔽最大化按钮API函数定义***********************
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex 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 WS_SYSMENU = &H80000
Private Const WS_MINIMIZEBOX = &H20000
Private Const WS_MAXIMIZEBOX = &H10000
Private Const GWL_STYLE = (-16)
'****************************************调用屏蔽关闭按钮过程**********************************
Set clsCloseButton = New class1
    clsCloseButton.EnableCloseButton Me.hWnd, False
'************************************************************************************************
Top
 
  回复人: DownFree(浅滩浮云) ( ) 信誉:100 2002-05-16 11:30:12 得分:0
 
 
 
其实完全没有必要去掉那个X,因为,如果你在Form_unload里面添加了代码,在用户通过X关闭窗体时,就会自动你自己的程序,可以试试看下面的代码:
private sub Form_unload(cancel as interger)
  debug.print "用户关闭!"
end sub
Top
 
  回复人: public(DarkTemplar) ( ) 信誉:100 2002-08-20 08:45:21 得分:0
 
 
 
to : daryl715(海军少校) (  ) 信誉:97
 clsCloseButton.EnableCloseButton Me.hWnd, False
enableclsoebutton 这个函数在哪呢????????????????????????????????????????????????????????????????????????
Top
 
  回复人: yxscd() ( ) 信誉:100 2002-08-20 09:26:19 得分:0
 
 
 
用程序语言是复杂了点,相比只下,我觉得用窗体属性还可以,我说的是
就你的问题而言。如果涉及到其他的话,不用代码,那也是不行的。楼上的
代码可以说够你用的了。
Top
 
  回复人: z2h(正好) ( ) 信誉:100 2002-08-20 09:32:14 得分:0
 
 
 
点击系统的关闭钮 窗体不见了 但还在系统进程中 说明没关闭程序 这怎么办??
Top
 
  回复人: myhfit() ( ) 信誉:105 2002-08-20 09:32:49 得分:0
 
 
 
其实关闭按钮和关闭菜单是关联的,只要屏蔽掉系统菜单就可以了。
具体为:1.用GetSystemMenu得到窗体的系统菜单,
2.用GetSubMenu得到关闭菜单项,
3.用EnabledMenu或DeleteMenu禁止或删除菜单项。
最大化和最小化按钮也可以这样做。
Top
 
  回复人: littleyaya(夕阳) ( ) 信誉:99 2002-08-20 10:18:31 得分:0
 
 
 
form 的 ControlBox属性设置为False。
Top
 
 

该问题已经结贴
 

你可能感兴趣的:(如何屏蔽掉窗口右上角的关闭按钮?)