• VC/MFC Q&A 200411


    Q 如何处理ComboBox中的回车键?避免退出程序?
    A 在一般的EDIT中采用的方法是处理PretranlateMessage(),执行代码
    CWnd *pWnd = GetFocus();
    if(pWnd != NULL)
    {
      if(pWnd == GetDlgItem(IDC_EDIT1)
      {
         ...//IDC_EDIT1具有焦点
      }
    }
     
    但在ComboBox中好象不同,是ComboBox的编辑控件得到了焦点,所以判断代码:
    BOOL CDlg::PreTranslateMessage(MSG *pMsg)
    {
       if(pMsg->message==WM_KEYDOWN && pMsg->wParam == VK_RETURN)
       {
          CWnd *pWnd = GetFocus();
          if(pWnd != NULL)
          {
             if(pWnd->GetParent() == GetDlgItem(IDC_COMBO1)//更改ID
             {
                   return TRUE;
             }
          }
       }
       return CDialog::PreTranslateMessage(pMsg);
    }

    //-------------------------------------------------
    Q 动态创建的组合框如何设置下拉列表框的高度?
    A m_combo.Create(WS_CHILD | WS_VISIBLE | WS_VSCROLL CBC_SORT | CBC_DROPDOWNLIST | WS_TABSTOP, CRect(320,10,580,280),this,114);
    //CRect的最后一个参数(这里是280)就表示下拉大小

    //-------------------------------------------------
    Q 是否能不选择下拉列表样式而禁止用户输入值,有什么方法可以实现?
    A 将下拉列表的编辑控件设置为只读的,方法如下:
    CComboBox *pcombo;
    CWnd *pWnd = pcombo->GetWindow(GW_CHILD);
    while(pWnd)
    {
      char classname[256];
      ::GetClassName(pWnd->m_hWnd,classname,256)
      if(strcmp(classname,"edit") == 0)
      {
         CEdit *pEdit;
         pEdit = new CEdit();
         pEdit->SubClassWindow(pWnd->m_hWnd);
         pEdit->SetReadOnly();
         pWnd = pWnd->GetNextWindow();
         delete pEdit;
      }
      if(pWnd)
         pWnd = pWnd->GetNextWindow();
    }

    //-------------------------------------------------
    Q ComboBox的自定义弹出菜单,想在右击组合框的编辑部分的时候弹出菜单?
    A 一种方法就是在CCustomCombo的OnCtlColor函数里进行,生成ComboBox中编辑框的子类,示例:
    HBRUSH CCustomCombo::OnCtlColor(CDC *pDC,CWnd *pWnd,UINT nCtlColor)
    {
      if(nCtlColor == CTLCOLOR_EDIT)
      {
         if(m_edit.GetSafeHwnd()==NULL)
            m_eidt.SubClassWindow(pWnd->GetSafeHwnd());
      }
      HBRUSH hbr = CComboBox::OnCtlColor(pDC,pWnd,nCtlColor);
      return hbr;
    }
    //其中m_edit是CEdit类的实现,它在WM_RBUTTONUP上显示右键菜单

    //-------------------------------------------------
    Q 如何给按钮加位图
    A
    对动态创建的按钮:
    CButton button;
    button.Create(_T("My Button"),WS_CHILD | WS_VISIBLE | BS_BITMAP,CRect(10,10,60,50),pParentWnd,1);
    button.SetBitmap(::LoadBitmap(NULL,MAKEINTRESOURCE(IBM_CHECK)));
    或者修改风格:
    UINT Style = Button.GetButtonStyle();
    Style = Style | BS_BITMAP;
    Button.SetBitmap(::LoadBitmap(NULL,MAKEINTRESOURCE(IBM_CHECK)));

    //-------------------------------------------------
    Q 如何在CButton派生类中以及父对话框中捕获BN_CLICKED消息?
    A 于WM_NOTIFY消息相反,通知消息BN_CLICKED作为WM_COMMAND消息发送。因此应用程序应该使用ON_CONTROL_REFLECT_EC而不是ON_NOTIFY_REFLECT

    //-------------------------------------------------
    Q 如何判断某个对象是否具有当前焦点?
    A return (CWnd::GetFocus() == pWnd);

    //-------------------------------------------------
    Q 如何设置编辑控件的数字限制属性?
    A
    long Style = GetWindowLong(m_EditCtrl.m_hWnd,GWL_STYLE);
    Style |= ES_NUMBER;
    SetWindowLong(m_EditCtrl.m_hWnd,GWL_STYLE,Style);

    //-------------------------------------------------
    Q 希望在LISTCTRL中显示文件,如何才能得到explorer使用的相同图象?
    A 可以将系统的ImageList加到LISTCTRL上,然后用具有SHGFI_ICON标志的SHGetFileInfo获取适当的图标索引:
    //图象列表设置
    HIMAGELIST himagelist;
    SHFILEINFO fi;
    CImageList m_smalllist;
    //得到系统小图标列表的句柄
    himagelist = (HIMAGELIST)SHGetFileInfo((LPCTSTR)_T("C://"),0,&fi,sizeof(SHFILEINFO),SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
    //添加到小图象列表
    m_smalllist.Attach(himagelist);
    //设置LISTCTRL的图象列表
    m_listCtrl.SetImageList(&m_smalllist,LVSIL_SMALL);
    //分离图象列表
    m_smalllist.Detach();

    //-------------------------------------------------
    Q 如何在列表的任何一列显示图标,而不是第一列?
    A
    LV_ITEM item;
    ...
    item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_PARAM;
    item.iItem = ...//设置行号
    item.lParam = ...//如何需要就设置lparam参数
    item.iSubItem = ...//设置列号,从0开始的
    item.stateMask = LVIS_STATEIMAGEMASK;
    item.state = INDEXTOSTATEIMAGEMASK(...);//参数为图标号
    item.iImage = ...//设置图标号
    item.pszText = ...//显示文本
    //插入新项
    m_listctrl.InsertItem(&item);
    //现在设置图标
    m_listctrl.SetItemText(0,4,szField);

    //-------------------------------------------------
    Q 给LISTBOX添加新项时如何实现自动下滚?
    A 在调用AddString后,添加如下代码:
    m_listbox.SetTopIndex(m_listbox.GetCount()-1);

    //-------------------------------------------------
    Q listBox的文本超过框的宽度时,如何让水平滚动条正常工作?
    A 用下面的代码,设置滚动条的宽度为最长的字符串宽度
    void SetHorizontalExtent(CListBox &listbox)
    {
        int index = listbox.GetCount();
        if(index == LB_ERROR)
           return;
        int nExtent = 0;
        if(index)
        {
            CDC *pDC = listbox.GetDC();
     CFont *poldfont = pDC->SelectObject(listbox.GetFont());
     CString s;
     SIZE text;
     LONG maxtxt = 0;
     whilw(index--)
     {
                 listbox.GetText(index,s);
          text = pDC->GetOutputTextExtent(s);
          if(text.cx > maxtxt)
                     maxtxt = text.cx;
      }
            text.cx = maxtxt;
          pDC->LPToDP(&text);
          nExtent = text.cx+2;
          pDC->SelectObject(poldfont);
          listbox.ReleaseDC(pDC);
        }  
        listbox.SetHorizontalExtent(nExtent);
    }

    //-------------------------------------------------
    Q 在拆分视图的时候,创建了四个视图(2行2列),右下的是CFormView,其他的都是CView,在CMainFrame的OnCreateCilent不管怎么指定CRect的大小,下方的两个视图都占了整个窗口,需要拖动!
    A 一般只需要在OnCreateClient的末尾添加:
    m_wndSpitter.SetRowInfo(0,200,0);//添加此行代码

    //-------------------------------------------------
    Q 如何指定拆分窗口的最小宽度?
    A 使用CSpitterWnd::SetColumnInfo()
      void SetColumnInfo(int col, //指定列
           int deal, //理想宽度(像素)
           int cxmin); //最小宽度(像素)
     在使用SetColumnInfo之后还应该调用RecalLayout();重新调整布局。
     
    //--------------------------------------------------
    Q 如何判断工具栏是水平还是垂直的?
    A if((m_toolbar.GetBarStyle() & CBRS_ALIGN_LEFT) == CBRS_ALIGN_LEFT ||

    (m_toolbar.GetBarStyle() & CBRS_ALIGN_RIGHT) == CBRS_ALIGN_RIGHT)
         AfxMessageBox("vertical");
      else
         AfxMessageBox("horizontal");

    //--------------------------------------------------
    Q 编程方式修改工具栏按钮的可见性?
    A 示例代码:
    DWORD style = m_toolbar.GetButtonStyle(nIndex);
    if(m_bHide)
       m_toolbar.SetButtonStyle(nIndex,style & ~WS_VISIBLE);
    else
       m_toolbar.SetButtonStyle(nIndex,style | WS_VISIBLE);
    m_bHide = !m_bHide;

    //--------------------------------------------------
    Q 如何在状态栏添加按钮并响应?
    A 创建一个从CButton派生的CMyButton类,在主框架类添加CMyButton类的成员变量,然后在OnCreate函数中创建按钮,并把它和状态栏关联起来:
    m_mybtn.Create("MyButton",WS_CHILD | VISIBLE,CRect(0,0,60,20),&m_WndStatusBar,0);
    通过处理BN_CLICKED消息,可以在CMyButton类中处理所有的点击事件

    //--------------------------------------------------
    Q 如何隐藏属性CPropertySheet的标题栏,使用ModifyStyle(WINDOW_CAPTION,0)没有效果
    A 创建自己的CPropertySheet派生类,并覆盖OnInitDialog,转到默认的情况后,使用ModifyStyle来删除WS_CAPTION标志

    //--------------------------------------------------
    Q 如何让属性页有两行标签?
    A 从CPropertySheet派生类,添加PreCreateWindow的处理,在调用基类之前添加代码:
     cs.style |= TCS_MULTILINE;

    //------------------------------------------------------
    Q 如何在属性表的两个页之间传递数据?
    A
    CPropertyPage有一个成员函数QuerySiblings(WPARAM, LPARAM)。应用程序可以使用这个函数。
    QuerySiblings生成一条PSM_QUERYSIBLINGS消息,它传递给所有的兄弟,也就是属性表上的其他属性页。   一般可创建一个所有页可见的枚举,如:
     enum{QUERY_MY_STRING,  QUERY_SOMETHING_ELSE,.......}
    然后,在一个属性页需要其他属性页中的信息时,使用代码:
    CString myString;
    if(lL == QuerySiblings(QUERY_MY_STRING,(LPARAM)&myString))
    {
             ....//获取字符串
    }
    提供字符串的页处理PSM_QUERYSIBLINGS消息:
    LRESULT CPageThatHasString::OnQuerySiblings(WPARAM wParam, LPARAM lParam)
    {
            if(QUERY_MY_STRING == wParam)
           {
                  *((CString *)lParam) = _T(“Test String“);
                   return 1L;
           }
           else
                  return 0L;
    }

    //----------------------------------------------------------
    Q  如何让属性页具有两行标签?

    从CPropertySheet派生一个自己的类,添加一个PreCreateWindow的处理,然后在调用基类的处理前加如下代码:cs.style |= TCS_MULTILINE;

    //-----------------------------------------------------------
    Q  如何隐藏属性页的标题栏?

    从CPropertySheet派生一个自己的类,并覆盖OnInitDialog,在转到默认的情况以后,使用 ModifyStyle来删除标题栏标志WS_CAPTION。
       ModifyStyle(WS_CAPTION,0);

    //-------------------------------------------------------------------
    Q 如何枚举桌面项目?
    A
    1 得到指向IShellFolder接口的指针
    2 得到指向IMalloc接口的指针
    3 得到指向IEnumIDList接口的指针
    4 提取枚举中下一项目的PIDL
    5 测定PIDL代表的标志符的类型
    6 处理该项目
    7 释放PIDL分配的内存
    8 重复4到7步,知道所有的项目都枚举完
    9 释放IShellFolder IMalloc IEnumIDList接口的指针

    LPSHELLFOLDER lpshellfolder;
    LPMALLOC lpmalloc;
    LPENUMIDLIST lpidlist;
    m_namecount = 0;
    HRESULT hr = SHGetDestopFolder(&lpshellfolder);
    if(hr == NOERROR)
    {
        hr = ::SHGetMalloc(&lpmalloc);
        if(hr == NOERROR)
        {
            hr = lpshellfolder->EnumObject(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,&lpidlist);
            if(hr == NOERROR)
                 ProcessFolder(lpshellfolder,lpmalloc,lpidlist);//custom deal function
            lpmalloc->Release();
            lpidlist->Release();
            InValidate();
        }
        lpshellfolder->Release();
    }
     
    void ***::ProcessFolder(LPSHELLFOLDER lpshellfolder,LPMALLOC lpmalloc,LPENUMIDLIST lpidlist)
    {
       STRRET strret;
       ULONG numfetch;
       LPITEMIDLIST lpitemlist;
       HRESULT hr = lpidlist->Next(1,&lpitemlist,&numfetch);
       while(hr == NOERROR)
       {
           ULONG attributes = SFGAO_FOLDER;
           lpshellfolder->GetAttributes(1,(const struct _ITEMIDLIST **)&lpitemlist,&attributes);
           if(attributes & SFGAO_FOLDER)
           {
               hr = lpshellfolder->GetDiaplayNameOf(lpitemlist,SHGDN_NORMAL,&strret);
               if(m_nameCount < 20)
                   m_names[m_namecount++] = strret.str;
           }
           lpmalloc->Free(lpitemlist);
           hr = lpidlist->Next(1,&lpitemlist,&numfetch);
       }
    }
    //-------------------------------------------------------------------
    Q  如何创建桌面快捷方式?
    A:
    1 initialize com
    2 create LShellLink Object
    3 Use IShellLink interface to get the pointer about IPersistFile
    4 Use IShellLink interface to initialize link
    5 Use LPersistFile interface to save the link
    6 Release all the com pointer
    7 Com return to previous status

    1
    HRESULT hr = CoInitialize(NULL);
    if(hr == S_OK)
    {
      ...//Continue
    }

    2
    IShellLink *pshelllink;
    pshelllink = CoCreateInstance(CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER,IID_IShellLink,(void **)&pshelllink);

    3
    IPersistFile *persistfile;
    persistfile = pshelllink->QueryInterface(IID_IPersistFile,(void **)&persistfile);

    4
    pshelllink->SetPath("C://config.sys");
    pshelllink->SetDescription("ShortCut to config.sys");

    5
    char path[MAX_PATH];
    GetWindowsDirectory(path,MAX_PATH);
    int len = strlen(path);
    strcpy(&path[len],"//desktop//config.lik");
    //change the char from ANSI to UNICODE
    OLECHAR widepath[MAX_PATH];
    MultiByteToWideChar(CP_ACP,0,path,-1,widepath,MAX_PATH);
    persistfile->Save(widepath,TRUE);

    6
    pshelllink->Release();
    psersistfile->Release();

    7
    CoUnInitialize();

  • 相关阅读:
    JZOJ 4043. 【雅礼集训2015Kzf】洪水
    JZOJ 5451.Genocide
    P4719 【模板】"动态 DP"&动态树分治
    [NOIP2018 提高组] 保卫王国
    【NOIP2017提高组正式赛】列队
    vuex的总结
    height:100vh
    从URL输入到页面展现到底发生什么
    JS的空数组是true还是false(内附JS类型转换表)
    Vue拼图验证组件使用教程
  • 原文地址:https://www.cnblogs.com/hehe520/p/6330139.html
Copyright © 2020-2023  润新知