如何在标题栏上添加按钮&通过例程分析状态条用法

如何在标题栏上添加按钮

  自从Windows操作系统出现以后,在应用程序中进行人机交互的思想和手段便发生了根本性的改变,计算机的界面变得友好精彩。一个程序的好坏很大程 度上决定于人机交互的方便程度。当前,大多数程序的标题栏都千篇一律,如何让自己的程序与众不同是每个程序员的梦想,但改变标题栏的内容的确有相当的难 度。该篇文章向你介绍如何在标题栏上添加图标按钮,而且当鼠标经过和点击该图标时,鼠标将有不同的反应。请按照下面的步骤实现。

  第一步:打开VC编程环境,生成一个新的基于单文档的工程temp,所有的选项都取默认值,下面,我们就在此工程的标题栏上生成三个按钮图标。

  第二步:下载资源文件,共有三个文件:CaptionButton.cpp、CaptionButton.h和Thunk.h。将这三个文件添加到工程中(添加方法不必细说了吧)。

  第三步:在Mainfrm.h中定义变量CCaptionButton cbExtra;,当然要包含头文件#include "CaptionButton.h"。

  第四步:为工程加载位图资源,ID号分别为IDB_BITMAP1、IDB_BITMAP2、IDB_BITMAP3、IDB_BITMAP6、IDB_BITMAP7。这些位图将显示在标题栏上,至于用什么样的位图就看你的喜好了。

  第五步:在Mainfrm.cpp的OnCreate函数中添加如下的代码:

//初识化,m_hWnd是我们要处理的窗口句柄
cbExtra.Init(m_hWnd);

// // 设置标题栏上的原来的按钮(最大化、最小化和关闭)保留的数目
cbExtra.SetNumOfDefaultCaptions(3);

// 设置位图的透明颜色
COLORREF crTransparent = RGB(255,0,255);
cbExtra.SetTransparentColor(crTransparent);

// 鼠标选中一个位图后该位图的样子
cbExtra.SetSelectionBitmap((HBITMAP)LoadImage(AfxGetInstanceHandle(),
   MAKEINTRESOURCE(IDB_BITMAP7),
   IMAGE_BITMAP,
   0,
   0,
   LR_LOADMAP3DCOLORS|LR_DEFAULTCOLOR)); 

// 鼠标移动到一个位图后,该位图的变化
HBITMAP hMouseOverBitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(),
   MAKEINTRESOURCE(IDB_BITMAP2),
   IMAGE_BITMAP,
   0,
   0,
   LR_LOADMAP3DCOLORS|LR_DEFAULTCOLOR);

// 设置位图1
HBITMAP hCaptionAMBitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(),
   MAKEINTRESOURCE(IDB_BITMAP3),
   IMAGE_BITMAP,
   0,
   0,
   LR_LOADMAP3DCOLORS|LR_DEFAULTCOLOR);

HBITMAP hCaptionAMBitmapHilite = 
   CCaptionButton::CombineBitmaps(hCaptionAMBitmap,
   hMouseOverBitmap, crTransparent);

// 设置位图2
HBITMAP hCaption2Bitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(),
   MAKEINTRESOURCE(IDB_BITMAP6),
   IMAGE_BITMAP,
   0,
   0,
   LR_LOADMAP3DCOLORS|LR_DEFAULTCOLOR);

HBITMAP hCaption2BitmapHilite = 
   CCaptionButton::CombineBitmaps(hCaption2Bitmap,
   hMouseOverBitmap,crTransparent);

// 设置位图三
HBITMAP hCaption3Bitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(),
   MAKEINTRESOURCE(IDB_BITMAP1),
   IMAGE_BITMAP,
   0,
   0,
   LR_LOADMAP3DCOLORS|LR_DEFAULTCOLOR);

HBITMAP hCaption3BitmapHilite = 
   CCaptionButton::CombineBitmaps(hCaption3Bitmap,
   hMouseOverBitmap,crTransparent);

// 利用上面的定义创建标题栏上的位图,宝库位图的ID号,鼠标经过时的
file://变换位图,鼠标选择时的变换位图和提示文字。

cbExtra.New(1,hCaptionAMBitmapHilite,hCaptionAMBitmap,"guan");
cbExtra.New(2,hCaption2BitmapHilite,hCaption2Bitmap,"xi");
cbExtra.New(3,hCaption3BitmapHilite,hCaption3Bitmap,"ming");
 

  第六步:现在我们可以先停下来看看我们的成果如何。编译我们的工程,运行,我们可以发现,我们的标题栏上增加了三个按钮,鼠标在上面移动或点击的时候,位图会发生变化。只是我们还没有添加在位图上点击是的处理函数,不要急,接下来我们就添加相应的处理函数。

  第七步:当我们在标题栏上点击图标时,将有一个消息WM_CBLBUTTONCLICKED产生,参数WPARAM是指点击图标的ID号。

  在mainfrm.h中定义消息映射函数afx_msg LRESULT Hit(WPARAM wParam, LPARAM lParam);

  在mainfrm.cpp中定义函数实现:

ON_MESSAGE(WM_CBLBUTTONCLICKED, Hit)
LRESULT CMainFrame::Hit(WPARAM wParam, LPARAM lParam)
{
      switch(wParam)
      {// begin wParam
            case 1:
                  AfxMessageBox("第一个CAPtion");
                  break;
            case 2:
                  AfxMessageBox("第二个Caption");
                  break;
            case 3:
                  AfxMessageBox("第三个Caption");
                  break;
      }
      return 1;


  这样,当我们单击图标时将弹出不同的提示对话框,这只是一个例子,至于实现什么样的功能随你的便了。

  第八步:标题栏的动态改变。在程序的执行过程中如果你要改变标题栏的样子你同样可以实现,下面分别给出如何删除一个图标和更改一个图标的样子。


void CMainFrame::OnDelete() 
{
      cbExtra.Delete(1);
}

void CMainFrame::OnChange() 
{
      cbExtra.Replace(1,
      1,
      hCaption4BitmapHilite,
      hCaption4Bitmap,
      "pNewToolTipText"); 
}
 
      好了,功能实现了,还算满意吧,希望对你有用。

 
通过例程分析状态条用法 
 
bull77  yesky

  状态条是一个包含信息的控制条,通常用于信息和状态提示,这里信息是有关菜单命令或工具命令的提示字符串以及其它指示/帮助信息,而状态是用来指示 SCROLL LOCK 和NUM LOCK等一些键的状态。状态条通常框架窗口的底部。状态条的信息行能显示有关的程序状态或鼠标指向的工具按钮或菜单 项的信息。状态条既不能接受用户输入,也不产生命令信息。

  实际上,从编程人员的角度出发(至少是那些使用AppWizard创建应用程序的编程人员),状态条是如此普通,它们并不像工具条那样允许用户编辑的 资源。在创建程序框架时,用户只需告诉AppWizard为应用程序包含一个状态条,可以说,此时,用户的工作就完成了。但是,我们如果巧妙使用工具条, 我们会发现它可以帮我们实现很多功能。

  按以下做法我们实现在状态条上显示滚动字符串,鼠标的坐标,动态时钟。

  第一步:

  运行AppWizard生成一个工程mystatus,接受所有的默认设置,除了下面两步:在step 1中选Single Document ; step 4 中去掉Docking Bar 前的对钩,然后点击 Advanced 按钮,选择Window Styles 中的 Maximized 选项。点击Finish按钮,此时我们生成了一个工程。运行我们可以发现程序默认生成的状态条,接下来我们要对这个状态条进行修改。

  第二步:

  在这一步我们将实现把状态条移到菜单的下边。在MainFrm.cpp中我们可以看到状态条的定义部分

  
  if (!m_wndStatusBar.Create(this) ||
    !m_wndStatusBar.SetIndicators(indicators,
    sizeof(indicators)/sizeof(UINT)))
   {
     TRACE0("Failed to create status bar/n");
      return -1; // fail to create
    }

   我们所要做的是将上面的定义改为

   if(!m_wndStatusBar.Create(this, WS_CHILD|WS_VISIBLE|CBRS_TOP,AFX_IDW_STATUS_BAR) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
  {
   TRACE0("Failed to create status bar/n");
   return -1; // fail to create
   }
 

运行程序,这时我们可以发现,状态条已经移到了上边。
 
  第三步:

  在这一步,我们实现在状态条实现滚动文字。

  < 1 > 在MainFrm.cpp中,我们可以发现如下的定义

  

  static UINT indicators[] =
   {
    ID_SEPARATOR,
    ID_INDICATOR_CAPS,
    ID_INDICATOR_NUM,
    ID_INDICATOR_SCRL,
   };

  我们将其改为

  static UINT indicators[] =
   {
    ID_SEPARATOR,
    ID_STATUS1, 
    ID_STATUS2, 
    ID_STATUS3, 
    ID_INDICATOR_CAPS,
    ID_INDICATOR_NUM,
    ID_INDICATOR_SCRL,
   };

 

  <2>在菜单VIEW中选择Resource Symbols , 在对话框中选择NEW, 在NAME中输入ID_STATUS1,VALUE中取默认值,同样方法定义ID_STATUS2,ID_STATUS3。

  <3>定义字符串资源,在ResouceView中选择String Table,在其中为ID_STATUS1定义字符串资源为"me",同样方法定义ID_STATUS2,ID_STATUS3。

  <4>在MainFrm.h中定义如下变量:

  public:

   CString str,str1;

  <5>在MainFrm.cpp中修改OnCreate函数如下:

  int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
   {
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
     return -1;
    if(!m_wndStatusBar.Create    (this,WS_CHILD|WS_VISIBLE|CBRS_TOP, AFX_IDW_STATUS_BAR) ||     !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)))
    {
     TRACE0("Failed to create status bar/n");
      return -1; // fail to create
     }
    m_wndStatusBar.SetPaneInfo(1,ID_STATUS1,SBPS_POPOUT,320);
    m_wndStatusBar.SetPaneInfo(2,ID_STATUS2,SBPS_POPOUT,100);
    m_wndStatusBar.SetPaneInfo(3,ID_STATUS3,SBPS_POPOUT,100);
    str1=str="你好,欢迎使用本程序,祝你合家幸福,事业有成!";
    SetTimer(1,200,NULL);
    SetTimer(2,10,NULL);
    return 0;
   }
 

  <6>在类CmainFrame中重载函数OnTimer(),并添加如下代码:

  void CMainFrame::OnTimer(UINT nIDEvent) 
   {
    file:// TODO: Add your message handler code here and/or call default
    if(nIDEvent==1){
     if(str.IsEmpty()) str=str1;
      str=str.Right(str.GetLength()-2);
      m_wndStatusBar.SetPaneText(1,str);
    }
    if(nIDEvent==2){
     SYSTEMTIME t;
     ::GetLocalTime(&t);
     CString str2;
     str2.Format("%d:%d:%d:%d",t.wHour,t.wMinute,t.wSecond,t.wMilliseconds);
     m_wndStatusBar.SetPaneText(3,str2);
   }
   CFrameWnd::OnTimer(nIDEvent);
  }
 

  <7>将MainFrm.h中,定义m_wndStatusBar之前的 protected: 改为public: 

  <8>通过类向导在类CmystatusView中重载WM_MOUSEMOVE,并在实现函数中添加如下代码:

  void CMystatusView::OnMouseMove(UINT nFlags, CPoint point) 
  {
   // TODO: Add your message handler code here and/or call default
   CString str3;
   str3.Format("X:%d,Y:%d",point.x,point.y);
   ((CMainFrame*)AfxGetMainWnd())->m_wndStatusBar.SetPaneText(2,str3);
    CView::OnMouseMove(nFlags, point);
  }
要在nRF52832的DFU(固件升级)例程添加一个服务,您可以按照以下步骤进行操作: 1. 打开nRF5 SDK的DFU例程,并根据您的开发环境配置好项目。 2. 打开`dfu_app_handler.c`文件,并添加以下代码来定义您的服务和特征: ```c #include "ble_dfu_service.h" // 定义DF服务UUID #define BLE_UUID_DFU_SERVICE 0x0001 // 定义DFU特征UUID #define BLE_UUID_DFU_CONTROL_CHARACTERISTIC 0x0002 // 定义全局变量 ble_dfu_service_t m_dfu_service; // 初始化DFU服务 static void dfu_service_init(void) { ble_dfu_service_init_t init; memset(&init, 0, sizeof(init)); init.evt_handler = NULL; // 设置事件处理函数,根据需要进行修改 ble_dfu_service_init(&m_dfu_service, &init); } // 应用程序初始化 static void app_init(void) { dfu_service_init(); } void dfu_app_on_dfu_evt(ble_dfu_evt_type_t evt_type) { switch (evt_type) { case BLE_DFU_START: // 处理DFU开始事件 break; case BLE_DFU_VALIDATE: // 处理DFU验证事件 break; case BLE_DFU_ACTIVATE_N_RESET: // 处理DFU激活和重启事件 break; default: // 其他事件处理 break; } } int main(void) { // 初始化BLE堆栈和其他必要的组件 // ... // 初始化应用程序 app_init(); // 启动主循环 while (1) { // 处理BLE事件 // ... } } ``` 3. 在项目文件夹中创建一个名为`ble_dfu_service.h`的新文件,并添加以下代码: ```c #ifndef BLE_DFU_SERVICE_H__ #define BLE_DFU_SERVICE_H__ #include <stdint.h> #include <stdbool.h> #include "ble.h" #include "ble_srv_common.h" // 定义DFU服务结构体 typedef struct { uint16_t service_handle; ble_gatts_char_handles_t control_handles; ble_uuid_t service_uuid; ble_uuid_t control_char_uuid; } ble_dfu_service_t; // 定义DFU服务初始化结构体 typedef struct { ble_dfu_service_evt_handler_t evt_handler; } ble_dfu_service_init_t; // 初始化DFU服务 void ble_dfu_service_init(ble_dfu_service_t * p_dfu_service, const ble_dfu_service_init_t * p_dfu_service_init); #endif // BLE_DFU_SERVICE_H__ ``` 4. 在项目文件夹中创建一个名为`ble_dfu_service.c`的新文件,并添加以下代码: ```c #include "ble_dfu_service.h" #include <string.h> // 初始化DFU服务 void ble_dfu_service_init(ble_dfu_service_t * p_dfu_service, const ble_dfu_service_init_t * p_dfu_service_init) { p_dfu_service->evt_handler = p_dfu_service_init->evt_handler; ble_uuid128_t base_uuid = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}; uint32_t err_code = sd_ble_uuid_vs_add(&base_uuid, &p_dfu_service->service_uuid.type); APP_ERROR_CHECK(err_code); p_dfu_service->service_uuid.uuid = BLE_UUID_DFU_SERVICE; err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &p_dfu_service->service_uuid, &p_dfu_service->service_handle); APP_ERROR_CHECK(err_code); ble_gatts_char_md_t char_md; memset(&char_md, 0, sizeof(char_md)); char_md.char_props.write_wo_resp = 1; // 设置写属性,无响应 ble_uuid_t char_uuid; char_uuid.uuid = BLE_UUID_DFU_CONTROL_CHARACTERISTIC; sd_ble_uuid_vs_add(&char_uuid.type, &char_uuid.uuid); ble_gatts_attr_md_t attr_md; memset(&attr_md, 0, sizeof(attr_md)); attr_md.write_perm = {1, 1}; // 设置写属性权限 ble_gatts_attr_t attr_char_value; memset(&attr_char_value, 0, sizeof(attr_char_value)); attr_char_value.p_uuid = &char_uuid; attr_char_value.p_attr_md = &attr_md; attr_char_value.max_len = sizeof(m_dfu_control_buffer); attr_char_value.init_len = sizeof(m_dfu_control_buffer); attr_char_value.p_value = m_dfu_control_buffer; err_code = sd_ble_gatts_characteristic_add(p_dfu_service->service_handle, &char_md, &attr_char_value, &p_dfu_service->control_handles); APP_ERROR_CHECK(err_code); NRF_SDH_BLE_OBSERVER(m_dfu_service_observer, 3, dfu_service_on_ble_evt, (void*) p_dfu_service); } ``` 请注意,上述代码仅提供了一个基本的框架和功能示例。您可能需要根据您的具体需求进行修改和扩展。 希望这可以帮助您在nRF52832的DFU例程添加一个服务。如果有任何进一步的问题,请随时提问。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值