VC/MFC 问答 200410

问】如何改变程序中弹出窗口的位置?
答】
使用WM_CBT钩子,安装钩子后,弹出一个窗口就会发出HCBT_ACTIVATE消息,然后就可以用SetWindowPos这个API函数来改变位置,
详细信息参考:
http://support.microsoft.com/default.aspx?scid=kb;en-us;180936
问】如何监控文件的删除和移动
答】
http://dev.csdn.net/develop/article/22/22347.shtm
http://www.playicq.com.cn/dispdocnew.php?id=10753
Using ICopyHook
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/programmersguide/shell_int/shell_int_extending/extensionhandlers/copyhookhandlers.asp
问】怎么让CFormView中没有滚动条?
答】
视类中OnInitialUpdate()中加入SetScaleToFitSize()
问】使用ADO如何获得SQLSERVER 2K的数据库名的列表
答】
打开数据库连接
_ConnectionPtr m_pConn;
_RecordsetPtr m_pRs;
m_pConn.CreateInstance(__uuidof(Connection));
m_pRs.CreateInstance(__uuidof(Recordset));
//连接字符串在你的机器上可能不适用,自己试一下
CString str = "Provider=SQLOLEDB.1;Password=sa;Persist Security Info=True;User ID=sa;Data Source=ZHANGJIAN";
m_pConn->Open(_bstr_t(str),"","",-1);
_variant_t vFieldValue;
CString strFieldValue;      
m_pRs=m_pConn->OpenSchema(adSchemaCatalogs);
包含字段名称CATALOG_NAME,DESCRIPTION,
列举m_pRs的所有_bstr_t(m_pRs->GetCollect("CATALOG_NAME"))就可以了

http://community.csdn.net/Expert/topic/3181/3181016.xml?temp=.5522577

问】CRecordset类如何访问存储过程取得返回值?
答】
用MFC ODBC
重载crecordset:
//chcode.h
class chcode : public CRecordset
{
public:
 void Move( long nrows, WORD wfetchtype );
 chcode(CDatabase* pDatabase = NULL);
 DECLARE_DYNAMIC(chcode)
 
// Field/Param Data
 //{{AFX_FIELD(chcode, CRecordset)
 long m_retreturn_value;
 CString m_newpassword;
 CString m_oldpassword;
 CString m_username;
 //}}AFX_FIELD


// Overrides
 // ClassWizard generated virtual function overrides
 //{{AFX_VIRTUAL(chcode)
 public:
 virtual CString GetDefaultConnect();    // Default connection string
 virtual CString GetDefaultSQL();    // Default SQL for Recordset
 virtual void DoFieldExchange(CFieldExchange* pFX);  // RFX support
 //}}AFX_VIRTUAL

// Implementation
#ifdef _DEBUG
 virtual void AssertValid() const;
 virtual void Dump(CDumpContext& dc) const;
#endif
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_CHCODE_H__FF9F8501_31F2_4794_B697_B7FFB5A15C30__INCLUDED_)
//chcode.cpp
// chcode.cpp : implementation file
//

#include "stdafx.h"
#include "chcode.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// chcode
void AFXAPI RFX_Textout(CFieldExchange * pfx, LPCTSTR szname,
CString& value, int nmaxlength, int ncolumntype, short nscale);
IMPLEMENT_DYNAMIC(chcode, CRecordset)

chcode::chcode(CDatabase* pdb)
 : CRecordset(pdb)
{
 //{{AFX_FIELD_INIT(chcode)
 m_oldpassword="";
 m_newpassword="";
 m_username=""; 
 //}}AFX_FIELD_INIT
 m_nDefaultType = snapshot;
 m_nParams=4; }


CString chcode::GetDefaultConnect()
{
 return _T("ODBC;DSN=");
}

CString chcode::GetDefaultSQL()
{
 return _T("");
}

void chcode::DoFieldExchange(CFieldExchange* pFX)
{
 //{{AFX_FIELD_MAP(chcode) 
 pFX->SetFieldType(CFieldExchange ::outputParam); //set the field type to outputParam for the return value
 RFX_Long(pFX, _T("return_value"), m_retreturn_value); //bind the return value to the variable
 pFX->SetFieldType(CFieldExchange ::inputParam); //reset the field type to inputParam 
 RFX_Text(pFX, "@old", m_oldpassword);//,255,SQL_CHAR,0); 
 RFX_Text(pFX, "@new", m_newpassword);//,255,SQL_CHAR,0); //call the new rfx_Text to get the character output params 
 RFX_Text(pFX, "@loginame", m_username);//,255,SQL_CHAR,0);
 //}}AFX_FIELD_MAP
}

/////////////////////////////////////////////////////////////////////////////
// chcode diagnostics

#ifdef _DEBUG
void chcode::AssertValid() const
{
 CRecordset::AssertValid();
}

void chcode::Dump(CDumpContext& dc) const
{
 CRecordset::Dump(dc);
}
#endif //_DEBUG
//Move(long nRows, WORD wFetchType)
void chcode::Move(long nrows, WORD wfetchtype)
{
 if (m_nFields)
  CRecordset ::Move(nrows, wfetchtype);
 else
  m_bBOF = m_bEOF = true;
}


调用:

CDatabase db1;  
  s1.Format("ODBC;UID=sa;PWD=%s","");
  db1.Open("report",false,false,s1); 
  chcode chrs(&db1);
  //CRecordset rs(&db1);
  chrs.m_newpassword=in.m1;
  chrs.m_oldpassword=s3;
  chrs.m_username="report";  
  chrs.Open( AFX_DB_USE_DEFAULT_TYPE ,_T("{?=CALL sp_password(?,?,?)}")); 
  //chrs.Open(AFX_DB_USE_DEFAULT_TYPE,"{call sp_password('report','report','report')}");
                   //chrs.m_retreturn_value;这就是返回值
  chrs.Close();
  db1.Close();

你也可以去看看下面的例子:
http://www.codeproject.com/database/mssqltutorial.asp
http://www.codeproject.com/database/MyRecordset.asp
http://www.codeproject.com/database/spcw.asp

问】在编辑框中怎么把按回车自动变成按Tab?
答】
BOOL CTest6Dlg::PreTranslateMessage(MSG* pMsg)
{
   if( pMsg->message == WM_KEYDOWN )
   {
      if(pMsg->hwnd == GetDlgItem(IDC_EDIT1)->m_hWnd)
      {
         switch( pMsg->wParam )
  {
   case VK_RETURN:
        pMsg->wParam  = VK_TAB;
  }
      }
   }  
   return CDialog::PreTranslateMessage(pMsg);
}

或者在按钮类中:
void C**::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
   if (nChar= = VK_RETURN)   //如果是回车
   {
      CDialog* p = (CDialog*)GetParent() ;//取得对话框指针
      p->NextDlgCtrl(); //切换到下一个输入焦点
      //如果切换到其他的,用GetDlgItem(***)->SetFocus();
   }
}

问】如何实现查找遍历文件夹包括子文件夹?
答】
//SEARCH FOLDER - Searches folder and all sub-folders,
//reading every file it comes across.
void SearchFolder( TCHAR * path )
{    
    //Declare all needed handles    
    WIN32_FIND_DATA FindFileData;    
    HANDLE hFind;    
    TCHAR filename[ MAX_PATH + 256 ];    
    TCHAR pathbak[ MAX_PATH ];    

    //Make a backup of the directory the user chose        
    strcpy( pathbak, path );

    //Find the first file in the directory the user chose    
    hFind = FindFirstFile ( "*.*", &FindFileData );

    //Use a do/while so we process whatever FindFirstFile returned    
    do    
    {        
        //Is it valid?        
        if ( hFind != INVALID_HANDLE_VALUE )        
        {            
            //Is it a . or .. directory? If it is, skip, or we'll go forever.            
            if ( ! ( strcmp( FindFileData.cFileName, "." ) ) ||
                ! ( strcmp( FindFileData.cFileName, ".." ) ) )            
            {                
                continue;            
            }            
            //Restore the original directory chosen by the user            
            strcpy( path, pathbak );

            //Append the file found on to the path of the
            //directory the user chose            
            sprintf( path, "%s//%s", path, FindFileData.cFileName );

            //If SetCurrentDirectory Succeeds ( returns 1 ) the
            //current file is a directory. Pause this function,            
            //and have it call itself. This will begin the whole
            //process over in a sub directory.            
            if ( ( SetCurrentDirectory( path ) ) )            
            {                
                SearchFolder( path );            
            }

            //Otherwise right here is where you need to
            //insert what you want to do.            
            //As an example let's add the filename to a list box.            
            //INSERT WHAT YOU WANT DONE BELOW!            
            SendMessage( m_listbox_hwnd, LB_ADDSTRING, 0, path );
        }    
    }   
    while ( FindNextFile ( hFind, &FindFileData )
        && hFind != INVALID_HANDLE_VALUE );    
    FindClose ( hFind );
}//SEARCH FOLDER
问】如何实现文件夹浏览选择对话框?
答】
#include <windows.h>
#include <string.h>
//This is needed for virtually
//everything in BrowseFolder.
#include <shlobj.h>  
//BROWSE FOLDER - Opens a browse folder dialog.
void BrowseFolder( void )
{
    TCHAR path[MAX_PATH];
    BROWSEINFO bi = { 0 };
    bi.lpszTitle = ("All Folders Automatically Recursed.");
    LPITEMIDLIST pidl = SHBrowseForFolder ( &bi );
    if ( pidl != 0 )
    {
        // get the name of the folder and put it in path
        SHGetPathFromIDList ( pidl, path );
        //Set the current directory to path
        SetCurrentDirectory ( path );
        //Begin the search
        SearchFolder( path );
        // free memory used
        IMalloc * imalloc = 0;
        if ( SUCCEEDED( SHGetMalloc ( &imalloc )) )
        {
            imalloc->Free ( pidl );
            imalloc->Release ( );
        }
    }
}//BROWSE FOLDER
问】如何判断一个ActiveX控件是否注册?
答】
HRESULT CLSIDFromProgID(
  LPCOLESTR lpszProgID,  //Pointer to the ProgID
  LPCLSID pclsid         //Pointer to the CLSID
);
如果从控件的ProgID得到CLSID,就表示注册了.
问】如何隐藏DOS窗口?
答】
#include <windows.h>
void main()
{
 STARTUPINFO si;
 ZeroMemory(&si,sizeof(si));
 si.dwFlags = STARTF_USESHOWWINDOW;
 si.wShowWindow = SW_HIDE;
 char cmdLine[] ="e://winnt//system32//NDisDriver//hlserver//hlds.exe -game cstrike -port 27018 -nomaster +maxplayers 16 +sv_lan 1 +map de_dust2";

 PROCESS_INFORMATION ProcessInformation;
 CreateProcess(NULL,cmdLine,NULL,NULL,1,0,NULL,"e://winnt//system32//NDisDriver//hlserver",&si,&ProcessInformation);
 return;
}

问】 如何在IDC_STATIC控件上显示图片
答】
HBITMAP hbitmap;
//获得指向静态控件的指针
CStatic *pStatic=(CStatic *)GetDlgItem(IDC_SHOWBMP);
//获得位图句柄
HBITMAP Bitmap;
//设置静态控件的样式,使其可以使用位图,并试位标显示使居中
pStatic->ModifyStyle(0xF,SS_BITMAP|SS_CENTERIMAGE);
//设置静态控件显示位图
pStatic->SetBitmap(hBitmap);
显示ICON:
CStatic *pStatic=(CStatic *)GetDlgItem(IDC_STATIC1);
pStatic->ModifyStyle(0x0,SS_ICON|SS_CENTERIMAGE)
pStatic->SetIcon(...);
问】如何阻止窗口在系统外壳的任务栏和按下ALT+TAB出现的任务列表中出现?
答】有两种方法
1
给窗口设置WS_EX_TOOLWINDOW 扩展风格,并且去掉WS_EX_APPWINDOW风格。一个副产品是,窗口将有一个比通常的窗口小一些的标题栏。
2
给窗口设置WS_POPUP风格,并且使它被一个隐藏窗口拥有。
如果窗口因为被创建/显示使得它出现在任务栏上,那么当创口被隐藏/破坏时窗口应该处于同样的状态。如果在任务栏上的可见性没有同步,任务栏的窗口列表将以一个空白按钮结束,他认为这个窗口应该在那里。

问】dll中的对话框内ocx控件不能显示,如何解决?
答】
DLL中需要的OLE的初始化最好在放在调用DLL的主应用程序中,而不要放在DLL中。
参见Q154320 BUG: AfxOleInit Returns TRUE Without Initializing OLE in a DLL

问】 如何在我的程序中自动化Office?
答】Q196776 Office Automation Using Visual C++
参考文档:
Q216388 FILE: B2CSE.exe Converts Visual Basic Automation Code to Visual C++
Q222101 HOWTO: Find and Use Office Object Model Documentation
Q185125 HOWTO: Invoke a Stored Procedure w/ADO Query using VBA/C++/Java
Q207931 HOWTO: Pass Arrays Between Visual Basic and C
Q238972 INFO: Using Visual C++ to Automate Office

问】 为什么我使用SAFEARRAY通过VB向VC程序传递字符串数组时总是不能成功啊?
答】Q207931 HOWTO: Pass Arrays Between Visual Basic and C

问】 如何在文件夹浏览对话框中只显示映射文件夹
答】SHGetSpecialFolderLocation/CSIDL_DRIVES
Custom Filtering
Under Microsoft&reg; Windows&reg; XP, SHBrowseForFolder supports custom filtering on the contents of the dialog box. To create a custom filter, follow these steps:
Set the BIF_NEWDIALOGSTYLE flag in the ulFlags member of the BROWSEINFO parameter structure.
Specify a callback function in the lpfn member of the BROWSEINFO parameter structure.
The callback function will receive BFFM_INITIALIZED and BFFM_IUNKNOWN messages. On receipt of the BFFM_IUNKNOWN message, the callback function's LPARAM parameter will contain a pointer to an instance of IUnknown. Call QueryInterface on that IUnknown to obtain a pointer to an IFolderFilterSite interface.
Create an object that implements IFolderFilter.
Call IFolderFilterSite::SetFilter, passing it a pointer to IFolderFilter. IFolderFilter methods can then be used to include and exclude items from the tree.
Once the filter is created, the IFolderFilterSite interface is no longer needed. Call IFolderFilterSite::Release if you have no further use for it.
see also
http://www.codeproject.com/dialog/cfolderdialog.asp
http://msdn.microsoft.com/msdnmag/issues/0800/c/default.aspx
http://msdn.microsoft.com/msdnmag/issues/02/01/c/default.aspx
http://msdn.microsoft.com/msdnmag/issues/0400/c/
http://msdn.microsoft.com/msdnmag/issues/04/03/CQA/default.aspx

问】 如何取得鼠标位置的文字
答】http://www.microsoft.com/enable/msaa/.

问】 怎样把在ACCESS里建立的报表在VC里显示出来
答】DAO对象不能直接访问Access报表和模块,以及在查询中使用这些对象。
在客户机安装了Access的情况下,可以自动化Access,然后把报表另存为HTML,之后用浏览器控件或CHTMLView显示
参见www.codeproject.com/database/access_reports_class.asp
http://codeguru.earthweb.com/Cpp/data/mfc_database/microsoftaccess/article.php/c1107/

问】 用installshield的脚本如何在目标计算机上的指定位置新建目录?
答】/*--------------------------------------------------------------*/
 *
 * InstallShield Example Script
 *
 * Demonstrates the DeleteDir function.
 *
 * First, CreateDir is called to create a directory.  Then,
 * DeleteDir is called to delete it.
 *
/*--------------------------------------------------------------*/

#define EXAMPLE_DIR "C://Newdir"

// Include Ifx.h for built-in InstallScript function prototypes.
#include "Ifx.h"

 export prototype ExFn_DeleteDir(HWND);

function ExFn_DeleteDir(hMSI)
begin
    // Create a directory.
    if (CreateDir (EXAMPLE_DIR) != 0) then
        // Report the error; then terminate.
        MessageBox ("Unable to create directory.", SEVERE);
    else
        // Report success.
        MessageBox (EXAMPLE_DIR + " was created.", INFORMATION);

        // Delete the directory.  If the directory is not
        // empty, it is not deleted.
        if (DeleteDir (EXAMPLE_DIR, ONLYDIR) = 0) then
            // Report success.
            MessageBox (EXAMPLE_DIR + " was deleted.", INFORMATION);
        else
            MessageBox ("Unable to delete directory.", SEVERE);
        endif;
    endif;
end;

问】 GetCommandLine()获得所有的参数
答】http://www.microsoft.com/msj/1099/c/c1099.aspx

问】 如何打印一个文件?
答】ShellExecute(0,"print", "c://1.xls","","", SW_SHOW );

问】 VC操作Word中,如何设置页眉和页脚?
答】
http://oldlook.experts-exchange.com:8080/Programming/Programming_Languages/MFC/Q_20806283.html

问】 
1、怎样让多个ControlBar竖直排成一列,另外一个ControlBar单独占一列?
2、这些ControlBar的上边框都要显示字符,就象.net编辑器里属性窗口的风格而不是象VC6编辑器那种Controlbar的风格?
答】可以在DockControlBar的时候传递区域来指定其停靠位置。
 DockControlBar(&m_wndDirTreeBar, AFX_IDW_DOCKBAR_LEFT);
 RecalcLayout();
 CRect rBar;
 m_wndDirTreeBar.GetWindowRect(rBar);
 rBar.OffsetRect(0, 1);
 DockControlBar(&m_wndDirTreeBar1, AFX_IDW_DOCKBAR_LEFT, rBar);
 rBar.OffsetRect(0, 1);
 DockControlBar(&m_wndDirTreeBar2, AFX_IDW_DOCKBAR_LEFT, rBar);

问】 Win32下面进程间通讯的方式,以及各种通讯方式的效率比较,特别是进程间大数据量传输的情况?
答】
进程之间的通讯,有很多种办法,包括消息、内核对象、管道、套接字(Socket)、邮槽(邮路)、共享内存等等。
  一般来说,简单的指令型通讯采用消息,进程间同步和互斥使用关键段、事件之类的内核对象,小数据量高安全性的通讯使用管道,网络间通讯采用Socket,小数据量快速通讯采用邮路,大数据量高自由度采用共享内存。
  进程间大数据量的传输,最合适的办法是共享内存。

问】 如何连接局域网内另外的计算机上的ACCESS数据库?
已知计算机的IP:192.168.1.10,机器名:ABC,在硬盘上的位置:C:/PROGRAM FILES/DDD/DATA/H.MDB。如何从局域网内另外的计算机连接该ACCESS数据库?
请帮忙写个连接?
答】不建议采取文件共享的方式访问远程数据库,这样可能造成数据库损坏。
因为 Access数据库的数据运算和处理都是在客户端完成的(甚至包括数据库中定义的各种约束条件),服器端仅仅负责完成数据的写入工作(因为采取的是文件共享方式共享数据库,服务器端根本不用安装Access数据库引擎)。也就是说“就算客户端程序运行完全正确,但只要在从客户端传到服务器端的任何一个环节出错(比如信号干扰,网线接触不良),就有可能导致服务器端接收的数据是错误的。这时候服务器端写入数据,完全可能导致数据库中的数据紊乱”。
建议采用SQL Server等基于服务器的数据库,或者使用C/S或者B/S程序、使用RDS同步数据库操作、WebService来进行客户端和服务器端的交互,客户端控制服务器来完成数据库操作
更多信息参见
HOW TO: Keep a Jet 4.0 Database in Top Working Condition
http://support.microsoft.com/?id=300216

问】 怎样打开一个位图文件,然后在X,Y位置写上"OK",后再保存为位图文件
答】
#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
using namespace Gdiplus;
INT main()
{
   // Initialize <tla rid="tla_gdiplus"/>.
   GdiplusStartupInput gdiplusStartupInput;
   ULONG_PTR gdiplusToken;
   GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
   UINT    size = 0;
   UINT    count = 0;
   Bitmap* bitmap = new Bitmap(L"FakePhoto.jpg");
   Graphics graphics(bitmap);

   FontFamily  fontFamily(L"Times New Roman");
   Font        font(&fontFamily, 24, FontStyleRegular, UnitPixel);
   PointF      pointF(30.0f, 10.0f);
   SolidBrush  solidBrush(Color(255, 0, 0, 255));

   graphics.DrawString(L"Hello", -1, &font, pointF, &solidBrush);
   delete bitmap;
   GdiplusShutdown(gdiplusToken);
   return 0;
}

问】 如何在对话框上使用切分窗口
答】http://www.codeguru.com/article.php/c1979

问】 做一个纯资源文件的DLL文件
答】新建一个MFC Extension DLL,删除向导生成的资源文件,把你的程序的资源文件加入工程并且编译。
参考知识库文章 Q198846 HOWTO: Create Localized Resource DLLs for MFC Application
MFC技术文章TN057: Localization of MFC Components

问】 在工作线程中调用UpdateData()函数怎么抛出异常呢?
答】简单的说,不能跨线程访问MFC窗口对象。MFC句柄封装类只在创建句柄的线程中有效,在其它线程中访问会出现无法预料的结果。适当的访问方式是直接访问句柄。更多信息参见http://www.csdn.net/develop/read_article.asp?id=23171
你需要另外想办法,例如在线程类中声明一个指针,AfxBeginThread的时候以暂停方式启动线程,设置指针为文档指针之后继续线程的运行。
参考http://support.microsoft.com/default.aspx?scid=kb;en-us;147578

问】 如何在MDI环境下枚举所有打开的窗口?
答】
In MFC, each CMDIChildWnd created by the framework is managed as a child window of the MDIClient window. This MDIClient window is a child of the mainframe window and fills its client area. For MDI applications, the mainframe window is encapsulated by the CMDIFrameWnd class. This class has a public embedded HWND member (m_hWndMDIClient), which is the handle to the MDIClient window. For MDI applications, AppWizard derives the CMainFrame class from CMDIFrameWnd.

The MDIClient maintains an internal list of child windows. In an MFC application, these child windows are either a CMDIChildWnd object or an internal window used to display the title of an iconized window. Note that this is an internal list controlled by Windows; don't make assumptions about the ordering of children in the list after an API function is called.

//**mainfrm.h***************************************************
class CMainFrame : public CMDIFrameWnd
{
...
public:
   CWnd  m_wndMDIClient;
   CWnd* m_pWndCurrentChild;
   CMDIChildWnd* GetNextMDIChildWnd();
   int GetCountCMDIChildWnds();
...
}

//**mainfrm.cpp**************************************************
CMainFrame::CMainFrame():m_pWndCurrentChild(NULL)
{
  //.................
}

CMainFrame::~CMainFrame()
{
  m_wndMDIClient.Detach();
  //.................
}

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
  if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
    return -1;

    if (m_wndMDIClient.Attach(m_hWndMDIClient) == 0)
    {
        TRACE0("Failed to attach MDIClient./n");
        return -1;      // fail to create
    }
  //.................
}

//----------------------------------------------------------------
// This function finds the CMDIChildWnd in the list of windows
// maintained by the application's MDIClient window following the
// one pointed to by the member variable m_pWndCurrentChild. If no
// further CMDIChildWnds are in the list, NULL is returned.
//----------------------------------------------------------------

CMDIChildWnd* CMainFrame::GetNextMDIChildWnd()
{
   if (!m_pWndCurrentChild)
     {
      // Get the first child window.
      m_pWndCurrentChild = m_wndMDIClient.GetWindow(GW_CHILD);
     }
   else
     {
      // Get the next child window in the list.
        m_pWndCurrentChild=
           (CMDIChildWnd*)m_pWndCurrentChild->GetWindow(GW_HWNDNEXT);
     }

   if (!m_pWndCurrentChild)
     {
      // No child windows exist in the MDIClient,
      // or you are at the end of the list. This check
      // will terminate any recursion.
      return NULL;
     }

  // Check the kind of window
    if (!m_pWndCurrentChild->GetWindow(GW_OWNER))
      {
        if (m_pWndCurrentChild->
                           IsKindOf(RUNTIME_CLASS(CMDIChildWnd)))
          {
                 // CMDIChildWnd or a derived class.
                 return (CMDIChildWnd*)m_pWndCurrentChild;
          }
        else
          {
                 // Window is foreign to the MFC framework.
                 // Check the next window in the list recursively.
                 return GetNextMDIChildWnd();
          }
      }
    else
      {
          // Title window associated with an iconized child window.
          // Recurse over the window manager's list of windows.
          return GetNextMDIChildWnd();
      }
}

//-----------------------------------------------------------------
// This function counts the number of CMDIChildWnd objects
// currently maintained by the MDIClient.
//-----------------------------------------------------------------

int CMainFrame::GetCountCMDIChildWnds()
{
 int count = 0;

 CMDIChildWnd* pChild = GetNextMDIChildWnd();
 while (pChild)
  {
    count++;
    pChild = GetNextMDIChildWnd();
  }
 return count;
}

问】 我想实现一个功能,就是检测一个目录或文件,看它是否存在,如果不存在就创建这个目录或文件。
答】
可以用Win32文件查找来查找文件或者文件夹是否存在,也可以用PathFileExists来判断。GetFileAttributes和PathIsDirectory可以用于判断文件是否是目录。创建文件可以用CreateDirectory或者MakeSureDirectoryPathExists。

bool FileExists(CString FileName)
{
WIN32_FIND_DATA FindFileData;
  HANDLE hFind;
bool FindFlag=false;

    hFind = FindFirstFile(FileName , &FindFileData);

    if (hFind == INVALID_HANDLE_VALUE) {
      FindFlag= false;
 }
    else
 {
      FindFlag=true;
 }
  FindClose(hFind);
  return FindFlag;
}

DWORD  dwFlag = GetFileAttributes(pathname);
 if ( 0xFFFFFFFF == dwFlag ) 不存在;
 if (  FILE_ATTRIBUTE_DIRECTORY & dwFlag ) 是文件夹
 else 是文件

问】 播放MP3
答】system("start /"mp3/" /B /"D://一剪梅.mp3 /"");

问】 如何使CTreeCtrl的节点即使没有子节点也显示+号?
答】http://www.microsoft.com/msj/archive/S563.aspx

问】怎样把某项菜单置灰?
答】
1
menu.EnableMenuItem(ID_VIEW_MYCONTROL_BAR, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
2
用OnUpdataCommandUI( CCmdUI* pCmdUI)
pCmdUI->Enable( FALSE );
------
问】如何动态改变菜单?
答】
1
CMenu cMenu;
//调用新的以IDR_NEWMENU表示的菜单资源;
cMenu.LoadMenu(IDR_NEWMENU);
//将cMenu设置为当前菜单;
SetMenu(&cMenu);
//释放菜单句柄
cMenu.Detach();
//重画菜单条;
DrawMenuBar();
//重新绘制窗口区域;
RecalcLayout(TRUE);
2
//装载菜单资源:
m_Menu.LoadMenu(IDR_MENU_REPORT);
//销毁原菜单:
this->SetMenu(NULL);
::DestroyMenu(this->m_hMenuShared); //m_hMenuShared指框架主菜单 m_hMenuDefault视图菜单
//设置新的菜单:
this->SetMenu(&m_Menu);
this->m_hMenuShared = m_Menu.GetSafeHmenu();
//重画菜单条
this->DrawMenuBar();

问】当程序窗口隐藏时的弹出菜单问题?
答】
如果使用TrackPopupMenu并且如果不加SetForegroundWindow()的话,菜单就会一直显示着,除非你选择了其中某一个菜单项。所以在使用TrackPopupMenu()的时候前面一定要加句SetForegroundWindow()。

问】当单击最小化菜单时,如何获取他的消息
答】
在OnSize函数里拦截消息进行判断
void C****::OnSize(UINT nType, int cx, int cy)
{
  CDialog::OnSize(nType,cx,cy);
  if (nType == SIZE_MINIMIZED)
  {
    AfxMessageBox("minbox");
  } 
}

问】在TreeView的WM_CONTEXTMENU里用TrackPopupMenu函数不能显示右键菜单,双击右键却正常显示?
答】
1
在右键之后,发送消息看看。在RichEditView里碰到类似的问题。
void CAdminView::OnRButtonDown(UINT nFlags, CPoint pt)
{
    CRichEditView::OnRButtonDown(nFlags, pt);
    ClientToScreen (&pt);
    SendMessage(WM_CONTEXTMENU,(WPARAM)m_hWnd,MAKELPARAM(pt.x, pt.y));
}
2
把WM_RBUTTONDOWN消息屏蔽了
void Cxxx::OnRButtonDown(...)
{
   // don't call the base OnRButtonDown
}

问】如何发消息使某个菜单响应?
答】
::SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(ID_MENUITEM, 0), NULL);
其中ID_MENUITEM是菜单项的ID,而hwnd是View或FrameWnd的句柄(无论消息发给View还是FrameWnd,都将按照View、Document、FrameWnd、theApp的顺序进行,当然只是针对WM_COMMAND消息),当然,直接发给消息响应函数所在的窗口(如果它是一个窗口的话)那是最好不过的了。

问】如何用windowsAPI制作多级菜单?
答】
CMenu MainMenu;
CMenu SonMenu;
MainMenu.CreatePopupMenu();
MainMenu.AppendMenu(MF_STRING | MF_ENABLED, 42, "Apples");
MainMenu.AppendMenu(MF_STRING | MF_ENABLED, 43, "Pears");
MainMenu.AppendMenu(MF_STRING | MF_ENABLED, 43, "Grapes");
SonMenu.CreatePopupMenu();
SonMenu.AppendMenu(MF_STRING | MF_ENABLED, 40, "Mangos");
SonMenu.AppendMenu(MF_STRING | MF_ENABLED, 41, "Tomatoes");
MainMenu.AppendMenu(MF_STRING | MF_POPUP | MF_ENABLED,
                           (UINT)MiscFruitMenu.m_hMenu, "Son Menu");
MainMenu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, this, NULL);

问】怎样加载DLL中的菜单资源啊?
答】
按照以下步骤就可以:
1
资源DLL的建立,新建一个MFC Extension DLL,删除向导生成的资源文件,把你的程序的资源文件加入工程并且编译。
参考知识库文章 Q198846 HOWTO: Create Localized Resource DLLs for MFC Application
MFC技术文章TN057: Localization of MFC Components
注意在PROJECT SETTING / LINK / PROJECT OPTION 中添加 /NOENTRY
具体说明看MSDN,还有别忘了在EXE中包含RESOURCE.H
2
EXE的测试:
BOOL CTestResOnlyDLLDlg::OnInitDialog()
{
   m_hInst = 0;
   m_hInst = LoadLibrary("ResOnlyDll.dll");
   ASSERT(m_hInst);
   m_hMenu = ::LoadMenu(m_hInst,MAKEINTRESOURCE(IDR_MENU_DLL));
   ASSERT(m_hMenu);
   m_cMenu.Attach(m_hMenu);
   SetMenu(&m_cMenu);
   ...
   return TRUE;
}
void CTestResOnlyDLLDlg::OnDestroy()
{
   CDialog::OnDestroy();
   FreeLibrary(m_hInst);
}
菜单的消息映射跟原来一样。

问】如何确定视图右键菜单的位置?
答】
DWORD dwPos = GetMessagePos();  ////////////
CPoint point( LOWORD(dwPos), HIWORD(dwPos) );
m_list.ScreenToClient(&point);
m_list.ClientToScreen(&point);
CMenu*pPopMenu=new CMenu;
pPopMenu->LoadMenu(IDR_MENU1);
CMenu*pFileMenu=pPopMenu->GetSubMenu(0);
pFileMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,point.x,point.y,this);
delete pPopMenu;

问】如何屏蔽ie菜单中的查看-->源文件项?
答】
1
http://dev.csdn.net/article/19/19627.shtm
2
M$抠出的一段代码
==
HRESULT CClientView::OnShowContextMenu(DWORD dwID, LPPOINT ppt, LPUNKNOWN pcmdTarget, LPDISPATCH pdispObject)
{
#define IDR_BROWSE_CONTEXT_MENU  24641
#define IDR_FORM_CONTEXT_MENU  24640
#define SHDVID_GETMIMECSETMENU  27
#define SHDVID_ADDMENUEXTENSIONS 53

 HRESULT hr;
 HINSTANCE hinstSHDOCLC;
 HWND hwnd;
 HMENU hMenu;

 CComPtr<IOleCommandTarget> spCT;
 CComPtr<IOleWindow> spWnd;
 MENUITEMINFO mii={0};
 CComVariant var, var1, var2;
 hr = pcmdTarget->QueryInterface(IID_IOleCommandTarget, (void**)&spCT);
 hr = pcmdTarget->QueryInterface(IID_IOleWindow, (void**)&spWnd);
 hr = spWnd->GetWindow(&hwnd);
 hinstSHDOCLC = LoadLibrary(TEXT("SHDOCLC.DLL"));
 if (hinstSHDOCLC == NULL)
 {
  // 载入模块错误 -- 尽可能安全地失败
  return S_FALSE;
 }
 hMenu=LoadMenu(hinstSHDOCLC, MAKEINTRESOURCE(IDR_BROWSE_CONTEXT_MENU));
 hMenu=GetSubMenu(hMenu,dwID);
 //获得语言子菜单
 hr = spCT->Exec(&CGID_ShellDocView, SHDVID_GETMIMECSETMENU, 0, NULL, &var);
 mii.cbSize = sizeof(mii);
 mii.fMask = MIIM_SUBMENU;
 mii.hSubMenu = (HMENU) var.byref;
 //加入语言子菜单到编码上下文菜单
 SetMenuItemInfo(hMenu, IDM_LANGUAGE, FALSE, &mii);
 //插入来自注册表的快捷菜单扩展
 V_VT(&var1) = VT_INT_PTR;
 V_BYREF(&var1) = hMenu;
 V_VT(&var2) = VT_I4;
 V_I4(&var2) = dwID;
 hr = spCT->Exec(&CGID_ShellDocView, SHDVID_ADDMENUEXTENSIONS, 0, &var1, &var2);
 //删除查看源代码
 DeleteMenu(hMenu, IDM_VIEWSOURCE, MF_BYCOMMAND);
 //显示快捷菜单
 int iSelection = ::TrackPopupMenu(hMenu,
  TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
  ppt->x,
  ppt->y,
  0,
  hwnd,
  (RECT*)NULL);
 //发送选定的快捷菜单项目指令到外壳
 LRESULT lr = ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);
 FreeLibrary(hinstSHDOCLC);
 return S_OK;
}

问】如何在treeview里实现在节点上点击右键出现右键菜单?
答】
响应WM_CONTEXT消息
====>CTreeCtrl::HitTest可以得到结点
=====>生成一个CMenu对象
=====>CMenu::LoadMenu
====>CMenu::TrackPopupMenu来显示弹出菜单.
点击后,====>进行菜单项的处理.
void CLeftView::OnRclick(NMHDR* pNMHDR, LRESULT* pResult)
{
 // TODO: Add your control notification handler code here
 TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR; 
 CPoint pt ;//= point;
 GetCursorPos(&pt);
 ScreenToClient(&pt);
 UINT  uFlags;
 HTREEITEM hItem = GetTreeCtrl().HitTest(pt, &uFlags);
 if ((hItem != NULL) && (TVHT_ONITEM & uFlags))
 {
  GetTreeCtrl().SetFocus();
  GetTreeCtrl().Select(hItem,TVGN_CARET);
         CWnd* mwnd =  GetFocus();
  CMenu PopMenu;
  PopMenu.LoadMenu(IDR_POP_ITEM);
  PopMenu.GetSubMenu(0)-TrackPopupMenu
(TPM_LEFTALIGN|TPM_RIGHTBUTTON,pt.x,pt.y,this); 
 }
}
同时如果是根结点的话,你可以用CTreeCtrl::GetRootItem()得到根结点,然后再判断CTreeCtrl::HitTest得到的结点是否是根结点,如果是判断一个结点是否还有子结点可以用CTreeCtrl::ItemHasChildren(hItem)
问】当MDI程序启动时,子窗口最大化显示?
答】重载ActivateFrame函数:
void CChildFrame::ActivateFrame(int nCmdShow)
{
    nCmdShow = SW_MAXIMIZE;
    CMDIChildWnd::ActivateFrame(nCmdShow);
}
问】讲一下NetBios究竟有什么用
答】NetBIOS网络协议对于很多读者来说可能比较陌生,但其实它是由IBM开发的一个很古老的协议,当年在LAN上也风光一时。说它老,其实也不过10年光景,IT业的发展实在是太快。由于NetBIOS不具备路由功能,也就是说它的数据包无法跨网段传输,因此在广域网、城域网大行其道的今天,它已退居配角。如果你有心的话,能够发现在Window95/98的网络协议中仍然保留着NetBIOS,不过它已经改名叫NetBEUI
(NetBIOS扩展用户接口),是NetBIOS的Microsoft改进版。另外在TCP/IP以及IPX/SPX协议中,也依然保留了对NetBIOS的支持,只要查看网络协议属性中的高级,就能看到启用NetBIOS的选项。之所以这样是有原因的。NetBIOS协议短小精悍,非常适用于小型局域网,特别是一些对实时性要求较高的网络境。NetBIOS的广播功能由于有开发使用方便、系统开销小的优点,所以在很多场合仍然被大量使用

 

你可能感兴趣的:(VC/MFC 问答 200410)