打算总结一些常见或者经典问题的答案,出一个新的CHM版。我开这个帖子的目的是希望有时间的朋友参与进来,呵呵!一起整理啊!
可以是以前帖子的,也可以直接从FAQ、精华帖找出来整理。我希望整理格式是:
【问题】......
【解答1】.....
【解答2】.....  10月2日结帖,希望大家积极参与整理。^_^

解决方案 »

  1.   

    这里是以前总结的:
    http://202.117.64.21/csdn/csdn.chm
    http://202.117.64.21/csdn/vcmfc.chm
    http://202.117.64.21/csdn/VC200402.chm
    http://202.117.64.21/csdn/index.chm
    以上四个我都试过,能下载。
      

  2.   

    http://community.csdn.net/Expert/FAQ/FAQ_Index.asp?id=198803
      

  3.   

    建议,如果是论坛里的帖子,htm页面最好做成论坛的格式
      

  4.   

    偶今天狂下了VC/MFC的FAQ共1225条,做成了CHM~挖哈哈
      

  5.   

    可以把csdn里的经典问题收集一下
      

  6.   

    以前下载过
    不过我一般查询CSDN历史记录。
      

  7.   

    faq:
    http://community.csdn.net/expert/FAQ/FAQ_Index.asp?id=198129
    希望能整理。
    [email protected]
      

  8.   

    【问题】怎样删除一个非空目录,及其目录里面所有内容:
    【解答1】如果不进行递归删除。你可以使用API函数SHFileOperation,它可以一次删除目录及其下面的子目录和文件。
        示例代码:
        BOOL DelTree(LPCTSTR lpszPath)
    {
      SHFILEOPSTRUCT FileOp;
      FileOp.fFlags = FOF_NOCONFIRMATION;
      FileOp.hNameMappings = NULL;
      FileOp.hwnd = NULL;
      FileOp.lpszProgressTitle = NULL;
      FileOp.pFrom = lpszPath;
      FileOp.pTo = NULL;
      FileOp.wFunc = FO_DELETE;
      return SHFileOperation(&FileOp) == 0;
    }【解答2】使用递归调用,逐个删除:
      示例代码:  BOOL DeleteDirectory(char *DirName)//如删除 DeleteDirectory("c:\\aaa") 
    {
    CFileFind tempFind;
    char tempFileFind[MAX_PATH];
    sprintf(tempFileFind,"%s\\*.*",DirName);
    BOOL IsFinded=(BOOL)tempFind.FindFile(tempFileFind);
    while(IsFinded)
    {
    IsFinded=(BOOL)tempFind.FindNextFile();
    if(!tempFind.IsDots())
    {
    char foundFileName[MAX_PATH];
    strcpy(foundFileName,tempFind.GetFileName().GetBuffer(MAX_PATH));
    if(tempFind.IsDirectory())
    {
    char tempDir[MAX_PATH];
    sprintf(tempDir,"%s\\%s",DirName,foundFileName);
    DeleteDirectory(tempDir);
    }
    else
    {
    char tempFileName[MAX_PATH];
    sprintf(tempFileName,"%s\\%s",DirName,foundFileName);
    DeleteFile(tempFileName);
    }
    }
    }
    tempFind.Close();
    if(!RemoveDirectory(DirName))
    {
    MessageBox(0,"删除目录失败!","警告信息",MB_OK);//比如没有找到文件夹,删除失败,可把此句删除
    return FALSE;
    }
    return TRUE;
    }
    原贴地址:http://community.csdn.net/Expert/topic/3384/3384830.xml?temp=.9723474
      

  9.   

    laiyiling(【陌生人 V2.0】) 收集整理问】如何判定剪贴板中有没有文本数据? 
    答】
    COleDataObject dataObject;
    dataObject.AttachClipboard();
    if(dataObject.IsDataAvailable(CF_TEXT))
    {
        .....//有文本数据
    }
    问】如何得到ComboBox的Edit句柄?
    答】CEdit *pEdit = (CEdit*)CComboBox.GetWindow(GW_CHILD)
    问】得到当前用户目录,即:C:\Documents and Settings\...
    答】SHGetSpecialFolderPath(NULL,(LPTSTR)szPath,CSIDL_PERSONAL,FALSE);
    问】状态栏的高度怎样改变?
    答】m_wndStatusBar.GetStatusBarCtrl().SetMinHeight(40);
    问】动态调整控件大小时需要注意的问题
    答】
    程序在执行WM_SIZE时,可能控件还没有被程序创建完成,你必须确保你的控件被创建后才能使用MoveWindow,
    1,你可以设一个BOOL变量,初值为FALSE,在OnInitDialog的最后将它的值变成TRUE,在WM_SIZE中判断这个变量,只有当它为真时才进行MoveWindow操作。
    2,你也可经先用::IsWindow(控件.GetSafeHwnd())判断控件是否创建,只有当它为真时才进行MoveWindow操作。
    问】在PreTranslateMessage()中如何取得组合键比如CTRL+F1
    答】if(pMsg->message ==WM_KEYDOWN&&pMsg->wParam==VK_F1 &&GetKeyState(VK_CONTROL)&0x80)
    问】SendMessage PostMessage的区别
    答】 
    PostMessage发送消息后就不等了,发了就回,管你处不处里呢 
    SendMessage发送消息后还要等消息被处理之后函数才返回
    更具体的解释可以看:
    http://msdn.microsoft.com/msdnmag/issues/1200/c/
    问】文档视图程序怎么使程序开始运行后不打开任何一个文档?
    答】
    MDI
    在程序的InitInstance中的ProcessShellCommand函数之前加入:
    cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing 
    SDI
    InitInstance函数中关于OnFileNew的调用去掉
    问】如何向一个按钮发送单击消息?
    答】
    SendMessage(WM_COMMAND,((WPARAM)BN_CLICKED)<<8|(WPARAM)IDC_BUTTON,0L);
    ::PostMessage(m_hWnd,WM_COMMAND,MAKEWPARAM(IDOK,BN_CLICKED),0);
    ::SendMessage(m_hWnd,WM_COMMAND,MAKEWPARAM(IDOK,BN_CLICKED),0);
    问】
    sdi工程,在关闭窗口的时候总是提示我是否保存?怎么才能不让这个窗口弹出直接关闭呢?
    答】
    void CMainFrame::OnClose() 
    {
        // TODO: Add your message handler code here and/or call default
        GetActiveDocument()->SetModifiedFlag(FALSE); //加入这句!
        CFrameWnd::OnClose();
    }
    问】如何得到其他应用程序的文本内容?
    答】发送WM_GETTEXT消息,而不能直接用GetWindowText函数,如果是用SDK,直接把CWnd换为HWND
    CWnd* pWnd = GetOtherAppWindow();
    TCHAR buf[512];
    pWnd->SendMessage(WM_GETTEXT,sizeof(buf)/sizeof(TCHAR),(LPARAM)(void*)buf);
    看到这里肯定有人会问?为什么GetWindowText函数不行呢?GetWindowText函数不就是发送WM_GETTEXT消息吗?不是。GetWindowText函数只有在窗口属于当前进程的时候才会发送WM_GETTEXT消息。如果窗口属于不同的进程,GetWindowText函数的行为是不一样的,MSDN的文档说的很清楚:
    如果目标窗口是属于其他进程的,并且窗口也有标题栏。GetWindowText函数返回窗口的标题。如果窗口没有标题栏则返回NULL。微软一开始就是这么设计GetWindowText函数的。也就是说我们用GetWindowText函数只能得到其他进程窗口的标题,而不能得到其他进程窗口里子窗口的文本内容,如:编辑矿、组合框。
    问】如何获知某进程打开了哪些文件? 
    答】http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c2827
    问】如何用CMyListCtrl(即自定义控件)取代CListView中的控件? 
    答】I made a custom control derived from CWnd, and now I want to use it as a view. My first solution was to embed the control into the view and handle OnSize in the view to position the control over the client area. The problem is that mouse messages go to the control and cannot be overridden in the view. The keystroke messages go to the view and must be manually forwarded to the control.
    I read about CCtrlView as a base class for common controls. I've even managed to write the view around it (I believe that you wrote about this in an issue of MSJ), but I could not get it to work with my CWnd-based control. Can this be done, and how?
    更多信息参见
    http://msdn.microsoft.com/msdnmag/issues/01/11/c/default.aspx
    问】谁能讲讲如何实现API钩子?
    答】My motivation for writing this article was the need for a really simple hooking framework, that will offer an easy to use interface and ability to capture different APIs. It intends to reveal some of the tricks that can help you to write your own spying system. It suggests a single solution how to build a set for hooking Win32 API functions on NT/2K as well as 98/Me (shortly named in the article 9x) family Windows. For the sake of simplicity I decided not to add a support for UNICODE. However, with some minor modifications of the code you could easily accomplish this task.
    For more infomation please read the following article,更多信息参见
    http://www.codeguru.com/Cpp/W-P/system/misc/article.php/c5667/
    问】// 激活当前屏幕保护程序可以发送如下消息
    答】PostMessage(WM_SYSCOMMAND,SC_SCREENSAVE,0);
    问】怎样得到屏幕的DC?
    答】CDC *dc=CDC::FromHandle(::GetDC(NULL));
    问】如何在状态栏里显示汉字?
    答】
    m_wndStatusBar.SetPaneText(nPane, sMsg);
    nPane是格子的序号,从0开始
    sMsg是显示的内容
    问】TabCtrl响应双击关闭
    答】可以用SetWindowLong设置上CS_DBLCLKS属性
    问】取得桌面的地址
    答】char szPath[1000];
    SHGetSpecialFolderPath(this->GetSafeHwnd(),szPath,CSIDL_DESKTOP,false);
    问】如何编程修改系统文件的显示属性?
    答】直接修改注册表可以。
    HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
    值Hidden,
    当这个值为2时,是“不显示隐藏的文件和文件夹”
    当这个值为1时,是“显示所有文件和文件夹”
    问】如何判断一个是否正被使用?
    答】
    HANDLE hf = CreateFile(cName,GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
    if(hf==INVALID_HANDLE_VALUE)
    {
      messageBox("该文件正在被使用,请关闭部分程序在试");
      return;
    }
    CloseHandle(hf);
    问】调试命令行参数程序时怎么输入参数?
    答】
    Project | Seeting | Debug 
    Program arguments中输入你的参数
    问】关于组合框的属性
    答】
    如果组合框具有不可输入只能下拉选择属性(DROPLIST),则直接关联的成员变量只能是int类型,你需要GetLBText()函数来获取当前选择的文本。(这是我们使用组合框时情况最多的一种)
    如果组合框除了下拉选择外还可以输入字符串(DropDown),则只能直接关联CString类型的成员变量。要获取当前选择的序号需要自己构造函数来完成 ComboBox下拉框的可视长度是指在create的时候指定的rect高度,就是combox下拉框的高度。
    问】如何编程打开关闭显示器?
    答】
    SendMessage(hWnd, WM_SYSCOMMAND,SC_MONITORPOWER,-1);  //打开显示器
    SendMessage(hWnd, WM_SYSCOMMAND,SC_MONITORPOWER,1);  //关闭显示器问】如何控制系统任务栏的显示和隐藏?
    答】
    //隐藏WINDOWS系统任务栏
     ::ShowWindow (::FindWindow("Shell_TrayWnd",NULL),SW_HIDE);
    //恢复WINDOWS系统任务栏正常显示
    ::ShowWindow (::FindWindow("Shell_TrayWnd",NULL),SW_SHOW);
    问】如何去掉树控件水平滚动条?
    答】long style  = GetWindowLong(Handle,GWL_STYLE);
    style |= TVS_NOHSCROLL;
    SetWindowLong(Handle,GWL_STYLE,style);
    ::ShowWindow(hwnd,SW_HIDE);
    问】怎样在CFormView去掉滚动条?
    答】
    在OnInitialUpdate函数里边,用下面的语句就OK了,
    SetScrollSizes(MM_TEXT,CSize(0,0))
    问】
    CRuntimeClass 的 m_pNextClass如何使用,我添加一个从CObject继承的类,实现了序列化,但是得到改类的CRuntimeClass 的m_pNextClass为空,为什么?
    有没有给定一个类的字符串名字,比如 "CMyObj",
    通过CRuntimeClass *pClass = RUNTIME_CLASS(CMyObj);pClass->CreateObject();创建对象.注意"CMyObj" 与CMyObj不同,是否能自动转换,或者使用CRuntimeClass 的字段m_lpszClassName进行匹配(关键是如何得到链表的头部)
    答】
    1) m_pNextClass 为空,表示你的类可能在链表尾部!
    2) 可以实现,部分代码如下:
    CObject* GetShapeClass(CString strClassName)
    {
     CRuntimeClass *pClass;
     AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); 
     for(pClass = pModuleState->m_classList;pClass!=NULL;
                  pClass=pClass->m_pNextClass) 
             {
      if(strClassName.Compare(pClass->m_lpszClassName)==0){
       return (pClass->CreateObject());
      }
     }
     return null;
    }
    返回的指针是cobject类型,你可以转换成正确的类型!
      

  10.   

    问】怎样编程改变某个文件夹的图标?
    答】
    只需要在指定的文件夹下建立Desktop.ini文件,其内容如下
    [.ShellClassInfo]
    IconFile=E:\资源\icon\icon\tree5s.ico
    IconIndex=0
    改变IconFile的值为你的图标
    并且设置该文件夹为系统属性
    问】VC程序怎样防止多重启动?
    答】
    初始化函数里创建互斥量,判断返回值
    BOOL CYourApp::InitInstance()
    {
       HANDLE Handle;
       Handle = CreateMutex(NULL,FALSE,_T("MakeSheet3.0"));
       if(Handle==NULL)
     return FALSE;
       if(GetLastError() == ERROR_ALREADY_EXISTS)
       {
     AfxMessageBox("MakeSheet3.0已运行!",MB_ICONSTOP);
     return FALSE;
       }
       ........
    }或者使用原子:#define AtomName "MyProgramNameAtom" //这个字串可以自己取,尽量取得特殊些int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        LPSTR lpCmdLine, int nCmdShow)
    {
        ATOM Atom;
        // 程序一开始,判断原子是否存在
        if (GlobalFindAtom(AtomName))
            return 1;  // 程序已经运行,这儿直接退出
        Atom = GlobalAddAtom(AtomName);
        //...... 你的代码
        // 程序退出前,删除原子
        GlobalDeleteAtom(Atom);  return 1;
    }
    参考:
    http://msdn.microsoft.com/msdnmag/issues/0900/c/default.aspx
    问】谁能介绍ASSERT函数的用法?
    答】
    ASSERT()是一个调试程序时经常使用的宏,在程序运行时它计算括号内的表达式,如果表达式为FALSE (0), 程序将报告错误,并终止执行。如果表达式不为0,则继续执行后面的语句。这个宏通常原来判断程序中是否出现了明显非法的数据,如果出现了终止程序以免导致严重后果,同时也便于查找错误。
    ASSERT只有在Debug版本中才有效,如果编译为Release版本则被忽略。
    ASSERT宏定义如下
    #define ASSERT(f) \
    do \
    { \
        if (!(f) && AfxAssertFailedLine(THIS_FILE, __LINE__)) \
            AfxDebugBreak(); \
    } while (0) \
    ASSERT(逻辑表达式)
    如果括号中的逻辑表达式值为假的话,会弹出调试命令窗口,提示具体在哪个文件的哪一行发生了断言错误!
    问】如何在建立文件时就分配好指定的磁盘空间?
    答】
    int iLength = 100000 ; 
    CFile file ; 
    file.Open(filename,CFile::modeCreate | CFile::modeWrite) ; 
    file.SetLength(iLength) ;
    这是通过文件操作控制的,也可以参考<Windows核心编程>第17章中介绍的文件映射。
    问】如何让对话框带上分割条?
    答】
    参考:http://www.codeproject.com/splitter/zsplitter.asp
    http://www.codeproject.com/splitter/simpledlgsplitter.asp
    问】谁做过UNICODE下,导出.CSV文件,怎么写入中文字符?
    答】
    应该就是文本写入吧!
    当然,不能使用CStdioFile的类,因为他不支持UNICODE的读写,我做的一个给你参考
    #ifndef __TEXTFILE_H
    #define __TEXTFILE_Hclass CTextFile : public CFile
    {
    public:
     virtual BOOL ReadString(CString& rString) {
    #ifdef _UNICODE
      if (GetPosition() == 0) {
       Seek(2, CFile::begin);
      }
    #endif  
      TCHAR tc;
      BOOL bFlag = false;  rString.Empty();
      while (CFile::Read(&tc, sizeof(TCHAR))) {
       switch (tc) {
       case 0x0D: break;
       case 0x0A:
        bFlag = true;
        break;
       default:
        rString += tc;
       }   if (bFlag)
        break;
      }
      return (!bFlag && rString.IsEmpty()) ? false : true;
     } virtual void WriteString(LPCTSTR lpsz) {
    #ifdef _UNICODE
      if (GetPosition() == 0) {
       char  tc[2];
       tc[0] = (char)0xFF;
       tc[1] = (char)0xFE;
       CFile::Write(tc, 2);
      }
    #endif
      CFile::Write(lpsz, _tcslen(lpsz) * sizeof(TCHAR));
     }
    };
    #endif //!__TEXTFILE_H
    问】如何获得指定网卡序号的Mac地址?
    答】
    提供一个函数供参考
    void CGetMacAddrDlg::GetOneMac(int AdapterIndex)
    {
        NCB ncb;
        UCHAR uRetCode;
     ASTAT Adapter;
        memset( &ncb, 0, sizeof(ncb) );
        ncb.ncb_command = NCBRESET;
        ncb.ncb_lana_num = AdapterIndex;   // 指定网卡号
     
     //首先对选定的网卡发送一个NCBRESET命令,以便进行初始化 
     uRetCode = Netbios( &ncb );    memset( &ncb, 0, sizeof(ncb) );
        ncb.ncb_command = NCBASTAT;
        ncb.ncb_lana_num = AdapterIndex;  // 指定网卡号    strcpy( (char *)ncb.ncb_callname,"*" );
     // 指定返回的信息存放的变量 
        ncb.ncb_buffer = (unsigned char *) &Adapter;
     ncb.ncb_length = sizeof(Adapter); // 发送NCBASTAT命令以获取网卡的信息 
     uRetCode = Netbios( &ncb );
        if ( uRetCode == 0 )
        {
      // 把网卡MAC地址格式化成常用的16进制形式,如0010-A4E4-5802 
      CString strMacAddr;
      strMacAddr.Format( "%02X%02X-%02X%02X-%02X%02X\n",
          Adapter.adapt.adapter_address[0],
          Adapter.adapt.adapter_address[1],
          Adapter.adapt.adapter_address[2],
          Adapter.adapt.adapter_address[3],
          Adapter.adapt.adapter_address[4],
          Adapter.adapt.adapter_address[5] );  //将网卡地址和序号存入数组中
      ADPTSTRCT AdptSt;
      AdptSt.nIndex = AdapterIndex;
      AdptSt.strMac = strMacAddr;
      m_arrAdapters.Add(AdptSt);
        }
    }void CGetMacAddrDlg::OnGetaddr() 
    {
     NCB Ncb; 
        UCHAR uRetCode; 
     LANA_ENUM lenum; 
     int i = 0; 
     
     memset(&Ncb, 0, sizeof(Ncb)); 
     Ncb.ncb_command = NCBENUM; 
     Ncb.ncb_buffer = (UCHAR *)&lenum; 
     Ncb.ncb_length = sizeof(lenum);  //向网卡发送NCBENUM命令,以获取当前机器的网卡信息,如有多少个网卡、每张网卡的编号等 
     uRetCode = Netbios( &Ncb ); 
     //获得所有网卡信息
     for(i=0; i < lenum.length ;i++)
     {
      GetOneMac(lenum.lana[i]);
     }
     
     //将保存到数组中的所有网卡信息在列表中显示
     int iActualItem;
     LV_ITEM lvitem;
     TCHAR buffer[128];
     for(int iItem=0;iItem<m_arrAdapters.GetSize();iItem++)
     {
      for(int iSubItem=0;iSubItem<2;iSubItem++)
      {
       lvitem.mask = LVIF_TEXT|(iSubItem == 0? LVIF_IMAGE : 0);
       lvitem.iItem = (iSubItem == 0)? iItem : iActualItem;
       lvitem.iSubItem = iSubItem;
       lvitem.iImage = (iItem%2)?0:2;
      
       if (iSubItem == 0)
       {//序号
        sprintf(buffer,"%d", m_arrAdapters.GetAt(iItem).nIndex);
        lvitem.pszText = buffer;
        iActualItem = m_ctrlAdaptersLst.InsertItem(&lvitem);
       }
       else
       {//Mac地址
        sprintf(buffer,"%s",m_arrAdapters.GetAt(iItem).strMac);
        lvitem.pszText = buffer;
        m_ctrlAdaptersLst.SetItem(&lvitem);
       }
      }
     }
    }
    问】如何让 Active X 控件支持 ON_MOUSEWHEEL 事件
    答】
    因为 COleControl 不直接支持 ON_MOUSEWHEEL 事件,但 COleControl 是从 CWnd 派生出来的,而 CWnd 是支持这一事件的,因此考虑在应用程序主类(CXXXCtrl)中直接使用 CWnd 类的消息函数。方法如下:
    1. 主类头文件(一般为XXXCtl.h) 
       消息映射段添加如下代码
       afx_msg void OnMouseWheel( UINT nFlags, short zDelta, CPoint pt );
    2. 主类源程序文件(一般为XXXCtl.cpp)
       在 BEGIN_MESSAGE_MAP 与 END_MESSAGE_MAP 中添加如下代码
       ON_WM_MOUSEWHEEL()
    3. 主类源程序文件
       添加函数实现代码如下
       void COCXCtrl::OnMouseWheel( UINT nFlags, short zDelta, CPoint pt )
       {
     RECT rect;
     GetClientRect( &rect );
     ClientToScreen( &rect );
     if ((pt.x <= rect.right)&&(pt.x >= rect.left )&&(pt.y <= rect.bottom )&&(pt.y >= rect.top ))
     {
      if (zDelta == WHEEL_DELTA)
      {
       // rotate forward (away from the user)
                    }
                    else
                    {
                               // rotate back (toward the user)
                    }
            }
            CWnd::OnMouseWheel( nFlags, zDelta, pt ); 
       }
    参考
    http://support.microsoft.com/default.aspx?scid=kb;en-us;231465
      

  11.   

    还有部分不帖了,我放在BLOG里面。
    http://blog.csdn.net/laiyiling/archive/2004/10/01/122928.aspx
    rivershan(笨猫)(www.rivershan.com) 已经整理了一个全部是FAQ的CHM版,所以暂时不会整理成CHM文件了,再过段时间等整理材料充足再说。
      

  12.   

    问题』(VFW视频采集)已有如下视频控制函数,如何根据视频窗口自动缩放视频大小?
    /*******************************************************************************  
         Function      :  EnablePreviewVideo  
         Arguments    :  Parent  (input)  -  Parent  window  that  will  display  video.  
                                   x  (input)  -  X  Location  in  parent  where  video  will  be  shown.  
                                   y  (input)  -  Y  location  in  parent  where  video  will  be  shown.  
                                   Width  (input)  -  Width  of  preview  window.  
                                   Height  (input)  -  Height  of  preview  window.  
                                   PreviewRate  (input)  -  Rate  of  preview  in  FPS.  
         Return          :  TRUE  Success,  FALSE  Failed.  
         Description:  Enables  preview  video  mode.  
    *******************************************************************************/  
    BOOL  CVFWImageProcessor::EnablePreviewVideo(HWND  Parent,  INT  x,  INT  y,  INT  Width,  INT  Height,  INT  PreviewRate)  
    {  
         //  Reset  any  error  conditions.  
         GetPreviousError(NULL,NULL,TRUE);  
     
         SetParent(m_hWndVideo,Parent);  
         SetWindowLong(m_hWndVideo,GWL_STYLE,WS_CHILD);  
     
         SetWindowPos(m_hWndVideo,NULL,x,y,  
                                   Width,  
                                   Height,  
                                   SWP_NOZORDER);  
         ShowWindow(m_hWndVideo,SW_SHOW);  
         capPreviewRate(m_hWndVideo,  PreviewRate);  
     
         return  capPreview(m_hWndVideo,TRUE);  
    }  解答』
    自动缩放视频到视频窗口大小:  
    在你的capPreviewRate(...)之后加上capPreviewScale(hwnd,TRUE)试试BOOL  capPreviewScale(  hwnd,  f  );  函数请参照MSDN:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_cappreviewscale.asp 
      

  13.   

    问题』(VFW视频)抓图如何获取视频的宽度和高度?
    解答』
    HWND  m_capwnd=capCreateCaptureWindow(.......);  
    BITMAPINFO  m_bmpinfo;  
    capGetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo));  
     
    m_bmpinfo.bmiHeader.biWidth和m_bmpinfo.bmiHeader.biHeight就是你想要的视频宽度和高度  
      

  14.   

    问题』(VFW视频)如何设置视频的宽度和高度?
    解答』
    BITMAPINFO  m_bmpinfo;  
    m_bmpinfo.bmiHeader.biWidth=176;//320  
    m_bmpinfo.bmiHeader.biHeight=144;//240  
    BOOL  ret=capSetVideoFormat(m_capwnd,&m_bmpinfo,sizeof(m_bmpinfo));
      

  15.   

    对laiyiling的热心表示敬佩!
    我也出份力。
    问】如何使用定时器
    答】作者:xujian
    一、定时器的基本使用方法在编程时,会经常使用到定时器。使用定时器的方法比较简单,通常告诉WINDOWS一个时间间隔,然后WINDOWS以此时间间隔周期性触发程序。通常有两种方法来实现:发送WM_TIMER消息和调用应用程序定义的回调函数。1.1 用WM_TIMER来设置定时器先请看SetTimer这个API函数的原型 UINT_PTR SetTimer(
      HWND hWnd,              // 窗口句柄
      UINT_PTR nIDEvent,      // 定时器ID,多个定时器时,可以通过该ID判断是哪个定时器
      UINT uElapse,           // 时间间隔,单位为毫秒
      TIMERPROC lpTimerFunc   // 回调函数
    );例如 
    SetTimer(m_hWnd,1,1000,NULL); //一个1秒触发一次的定时器
    在MFC程序中SetTimer被封装在CWnd类中,调用就不用指定窗口句柄了,例如:UINT SetTimer(1,100,NULL); 
    函数反回值就是第一个参数值1,表示此定时器的ID号。第二个参数表示要等待100毫秒时间再重新处理一次。第三个参数在这种方法中一般用NULL。
    注意:设置第二个参数时要注意,如果设置的等待时间比处理时间短,程序就会出问题了。1.2 调用回调函数此方法首先写一个如下格式的回调函数void CALLBACK TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime);
    然后再用SetTimer(1,100,TimerProc)函数来建一个定时器,第三个参数就是回调函数地址。二、多个定时器的实现与应用我们在安装定时器时都为其指定了ID,使用多个定时器时,该ID就发挥作用了。
    不使用MFC时,当接收到WM_TIMER消息,WPARAM wParam中的值便是该定时器的ID
    使用MFC时就更简单了,我们为其增加WM_TIME的消息处理函数OnTimer即可,请看如下例子 
    void CTimerTestDlg::OnTimer(UINT nIDEvent) 
    {
    switch (nIDEvent)
    {
    case 24:  ///处理ID为24的定时器
    Draw1();
    break;
    case 25:  ///处理ID为25的定时器
    Draw2();
    break;
    }
    CDialog::OnTimer(nIDEvent);
    }
    当你用回调函数时,我们可以根据nTimerid的值来判断是哪个定时器,例如: 
    void CALLBACK TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime)
    {
       switch(nTimerid)
       {
       case 1:  ///处理ID为1的定时器
             Do1();
             break;
       case 2:  ///处理ID为2的定时器
             Do2();
             break;
       }
    }
    三、取消定时器不再使用定时器后,我们应该调用KillTimer来取消定时,KillTimer的原型如下BOOL KillTimer(
      HWND hWnd,          // 窗口句柄
      UINT_PTR uIDEvent   // ID
    );
    在MFC程序中我们可以直接调用KillTimer(int nIDEvent)来取消定时器。问】什么是内存文件 如何使用
    答】内存文件从行为特征,操作上都与磁盘文件一样。不同的是内存文件是驻留于内存的,
    而不是存储在磁盘上。内存文件因驻留于内存,所以比磁盘文件快,因为是与内存交换数据
    的这一特点,内存文件常用来做临时文件,或在不同的应用程序中交换少量数据或对象,所
    以内存文件成为多进程共享数据进行通信的重要手段之一。
    下面来介绍一下操作内存文件的一个类:CMemFile
    CMemFile类就是MFC提供的对内存进行创建和操作的类,它是由CFile派生的。
    CMemFile对象可以自动分配或由人工调用Attach函数进行分配。
    此外CMemFile对象所创建的内存文件是自动打开的,不必调用CFile::Open
    之类的函数,因为对磁盘操作的打开和关闭文件不在适用
    于CMemFile对象。CMemFile对象也不支持CDuplicate函数,LockRage
    函数,和UnLockRange函数。
    其特色函数如下:
    Attach()    将内存附到CMemFile对象 
    Detach()    将一内存块从CMemFile对象 上分离出来,返回内存指针
    Alloc()        虚拟函数内存分配操作
    Free()        解除内存配置
    Realloc()    从新分配内存
    Memcpy()    对内存文件进行拷贝
    GrowFile()    处理内存文件增长 
      

  16.   


    问】如何读写注册表?
    答】
     Win 95及NT的注册数据库(Registry)是系统中非常重要的组成部分。在Win32 API中有一组Reg函数来处理这些问题。其一般的读写过程如下:
     
        1、使用RegOpenKeyEx或RegCreateKeyEx函数打开或创建一个键; 
        2、如果上一步成功,使用RegQueryValueEx读取子键的值,使用RegSetValueEx设置子键值,使用RegEnumKey获得所有子键,使用RegDeleteKey删除一个键; 
        3、完成操作后使用RegCloseKey关闭键。 
        下面这段程序打开HKEY_CURRENT_USER\Software\Zeal SoftStudio\AskPro FTP\LastTime键,然后读取WOL子键的值。     HKEY hkey; 
        char sz[256]; 
        DWORD dwtype, sl = 256; 
         
        RegOpenKeyEx(HKEY_CURRENT_USER, 
        "Software\\Zeal SoftStudio\\AskPro FTP\\LastTime", 
        NULL, KEY_ALL_ACCESS, &hkey); 
        RegQueryValueEx(hkey, "WOL", NULL, &dwtype, (LPBYTE)sz, &sl); 
        RegCloseKey(hkey); 
        MFC程序可以使用CRegKey类读写注册表。VB中调用API的办法可以参考QA000226 "如何访问Windows系统注册表"。    打开注册键
        LONG RegOpenKeyEx( HKEY hKey,  // handle to open key     LPCTSTR lpSubKey,              // address of name of subkey to open 
        DWORD ulOptions,               // reserved =0
        REGSAM samDesired,             // security access mask 
        PHKEY phkResult                // address of handle to open key 
        );    例:
        HKEY hd;
        hd=HKEY_LOCAL_MACHINE;
        char* Regkeyname="SoftWare\\Xy123\\Poker\\";
        LONG a=RegOpenKeyEx(hd,Regkeyname,0,KEY_READ,&hd);   //成功返回ERROR_SUCCESS,否则返回错误代码
         关闭注册键
        LONG RegCloseKey( HKEY hKey // handle to key to close );
    例:
         RegCloseKey(HKEY_LOCAL_MACHINE);
    OR:  RegCloseKey(hd); 
    建立注册键
    LONG RegCreateKeyEx( HKEY hKey, // handle to an open key 
          LPCTSTR lpSubKey, // address of subkey name 
          DWORD Reserved, // reserved =0
          LPTSTR lpClass, // address of class string 
          DWORD dwOptions, // special options flag 
          REGSAM samDesired, // desired security access       LPSECURITY_ATTRIBUTES lpSecurityAttributes, // address of key security         structure 
          PHKEY phkResult, // address of buffer for opened handle 
          LPDWORD lpdwDisposition // address of disposition value buffer );
    例:
       char *sclass="";  //类名指定为空
       DWORD nbf=0;    //接受返回值,指明是建立新键还是打开已有的键.(经试验总是返回REG_OPENED_EXISTING_KEY.
       LONG II=RegCreateKeyEx(hd,Regkeyname,0,sclass,REG_OPTION_NON_VOLATILE,
                    KEY_READ|KEY_WRITE,NULL,&hd,&nbf);//REG_OPTION_NON_VOLATILE 指明键永久保留.安全结构指明NULL,自动获得一默认值
    //成功返回ERROR_SUCCESS,否则返回错误代码 
    枚举键值
    LONG RegEnumValue( HKEY hKey, // handle to key to query 
          DWORD dwIndex, // index of value to query 
          LPTSTR lpValueName, // address of buffer for value string 
          LPDWORD lpcbValueName, // address for size of value buffer 
          LPDWORD lpReserved, // reserved =NULL
          LPDWORD lpType, // address of buffer for type code       LPBYTE lpData, // address of buffer for value data 
          LPDWORD lpcbData // address for size of data buffer);
    例:
       DWORD dinx=0;
       char valuename[70];  //分配数值名称缓冲区
       strcpy(valuename,"DeskPattern");  //随便指定哪个键值名
       DWORD nsize=69;  //数值名称缓冲区大小
       DWORD k=REG_SZ;  //指明数据类型
       unsigned char vari[70]; //分配数值缓冲区
       DWORD ncbvari=69; //数值缓冲区大小
       dinx=0; //从0开始   while((II=RegEnumValue(hd,dinx,valuename,&nsize,NULL,&k,vari,&ncbvari)) 
              != ERROR_NO_MORE_ITEMS)
       {
           dinx++;//索引 +1,准备取下一个值
           nsize=69; //恢复原来大小
           ncbvari=69;
       }
    成功后返回值0,各变量返回后设置如下:
    valuename=数值名称,以0结尾;如 : DeskColor
    nsize=数值名称长度, 9
    k=REG_SZ  DeskColor 的类型为 REG_SZ
    vari=键值,32768 DeskColor="32768",
    ncbvari=键值长度 REG_SZ包括结尾0,=6, 
    读取键值
    LONG RegQueryValueEx( HKEY hKey, // handle to key to query        LPTSTR lpValueName, // address of name of value to query 
           LPDWORD lpReserved, // reserved 
           LPDWORD lpType, // address of buffer for value type 
           LPBYTE lpData, // address of data buffer 
           LPDWORD lpcbData // address of data buffer size );
    例:
       RegQueryValueEx(hd,valuename,NULL,&k,vari,&ncbvari);
    变量定义及成功后各变量设置值同RegEnumValueEx 
    写键值
    LONG RegSetValueEx( HKEY hKey, // handle to key to set value for 
           LPCTSTR lpValueName, // name of the value to set        DWORD Reserved, // reserved 
           DWORD dwType, // flag for value type 
           CONST BYTE *lpData, // address of value data 
           DWORD cbData // size of value data );
    例:
       strcpy(valuename,"Hello");
       unsigned char vari[10];
       DWORD k=REG_SZ;
       strcpy((char*)vari,"1234567")
       RegSetValueEx(hd,valuename,0,k,vari,7);
    成功后在Poker下增加一个键值 Hello : REG_SZ : 1234567
    写整型变量:
    int hi=8;
    RegSetValueEx(pj,valuename,0,REG_BINARY,(unsigned char*)&hi,sizeof(int));成功后在Poker下增加一个键值 Hello2 : REG_BINARY :08 00 00 00void AddEventSource()
    {
        HKEY hk; 
        DWORD dwData; 
        UCHAR szBuf[80];     // Add your source name as a subkey under the Application 
        // key in the EventLog registry key.     if (RegCreateKey(HKEY_LOCAL_MACHINE, 
                "SYSTEM\\CurrentControlSet\\Services\ 
                \\EventLog\\Application\\SamplApp", &hk)) 
            ErrorExit("Could not create the registry key.");     // Set the name of the message file.     strcpy(szBuf, "%SystemRoot%\\System\\SamplApp.dll");     // Add the name to the EventMessageFile subkey.     if (RegSetValueEx(hk,             // subkey handle 
                "EventMessageFile",       // value name 
                0,                        // must be zero 
                REG_EXPAND_SZ,            // value type 
                (LPBYTE) szBuf,           // pointer to value data 
                strlen(szBuf) + 1))       // length of value data         ErrorExit("Could not set the event message file.");     // Set the supported event types in the TypesSupported subkey.     dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | 
            EVENTLOG_INFORMATION_TYPE;     if (RegSetValueEx(hk,      // subkey handle 
                "TypesSupported",  // value name 
                0,                 // must be zero 
                REG_DWORD,         // value type 
                (LPBYTE) &dwData,  // pointer to value data             sizeof(DWORD)))    // length of value data 
            ErrorExit("Could not set the supported types.");     RegCloseKey(hk); 
    } 以下代码把注册表自启动shell的键值改写为C:\DK1\ATM\HARP\ExAtmShell.exe:         HKEY hkey;
    LONG res; 
    DWORD datatype=REG_SZ; 
    unsigned char szvalue[_MAX_PATH];
    strcpy((char*)szvalue,"C:\\DK1\\ATM\\HARP\\ExAtmShell.exe");

    res =::RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
    "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\", 0, 
    KEY_WRITE|KEY_READ, &hkey);  if(res!=ERROR_SUCCESS)
    {
    AfxMessageBox("aaa");
    return;
    }
    res = ::RegSetValueEx(hkey, "Shell", 0, datatype, szvalue, strlen(LPCSTR(szvalue))); RegCloseKey(hkey);
    if(res==ERROR_SUCCESS)
    ::AfxMessageBox("你已经成功地将注册表自启动shell的键值设置为C:\\DK1\\ATM\\HARP\\ExAtmShell.exe");
    else
    ::AfxMessageBox("设定失败:目标位置不存在这样的键!");
      

  17.   

    问』如何从DLL中得到自己的路径?
    答』使用GetModuleFileName函数
    代码实例:
    #include "stdafx.h"HINSTANCE g_hInst;
    char gszFileName [MAX_PATH];  //stores the resultBOOL APIENTRY DllMain( HANDLE hModule, 
                           DWORD  ul_reason_for_call, 
                           LPVOID lpReserved
     )
    {
    g_hInst = (HINSTANCE)hModule;
        return TRUE;
    }extern "C" __declspec(dllexport) HRESULT DllRegisterServer(void)
    {
    ::GetModuleFileName(g_hInst, gszFileName, MAX_PATH);
    ::MessageBox(0, gszFileName, "Test", MB_OK);
    return 0;
    }
      

  18.   

    问』如何解决这个常见的错误?
    --------------------Configuration: HelloMsg - Win32 Debug--------------------
    Linking...
    LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
    Debug/HelloMsg.exe : fatal error LNK1120: 1 unresolved externals
    Error executing link.exe.
    答』去掉project->setting->link->project option中
    /subsystem:windows
      

  19.   

    一下是得到CPU的一些信息,都是搜集来的:// 得到CPUOEM
    char * GetCPUOEM(void)
    {
    char OemStr[13]; _asm
    {
    mov eax,0
    cpuid
    mov DWORD PTR OemStr,ebx
    mov DWORD PTR OemStr+4,edx
    mov DWORD PTR OemStr+8,ecx
    mov BYTE PTR OemStr+12,0
    }         TCHAR szCpuOEM [MAX_PATH] ;
    _stprintf ( szCpuOEM ,TEXT ( "%s" ) , OemStr) ; return szCpuOEM ;
    }// 得到CPU速度
    inline unsigned __int64 theCycleCount(void)
    {
    _asm _emit 0x0F
    _asm _emit 0x31
    //
    }
    class CTimer
    {
    unsigned __int64 m_start;
    public:

    unsigned __int64 m_overhead;

    CTimer(void)
    {
    m_overhead = 0;
    Start(); /// we get the start cycle
    m_overhead = Stop();
    // then we get the stop cycle catching the overhead time
    }

    void Start(void)
    {
    m_start = theCycleCount();
    }
    unsigned __int64 Stop(void)
    {
    /// with the stop cycle we remove the overhead's time
    return theCycleCount()-m_start-m_overhead;}
    };然后使用这个函数
    double GetCPUSpeed(void)
    { TCHAR szRawClockFreq [MAX_PATH] ; CTimer timer;

    long tickslong;
    long tickslongextra;
    timer.Start(); 
    Sleep(1000); 
    unsigned cpuspeed100 = (unsigned)(timer.Stop()/10000);


    tickslong = cpuspeed100/100;
    tickslongextra = cpuspeed100-(tickslong*100); _stprintf ( szRawClockFreq , TEXT ( "%d.%d" ) , tickslong , tickslongextra ) ; return (atof(szRawClockFreq));
    }// 98下得到CPU使用率
    使用性能计数器
    第一步:因为所有的计数器缺省情况下是停止的,所以要启动所要的计数器。为此我们必须读取相关的注册表键值。
    1。
    DWORD dwDataSize;
    DWORD dwType;
    DWORD dwCpuUsage;
    DWORD dwDummy;
    HKEY hkey;2 .初始化函数中:
    HKEY hkey;

    RegOpenKeyEx ( HKEY_DYN_DATA,
    "PerfStats\\StartStat",
    0,KEY_ALL_ACCESS,
    &hkey ); 

    dwDataSize=sizeof(dwDummy); 
    RegQueryValueEx ( hkey,
    "KERNEL\\CPUUsage",
    NULL,&dwType,
    (LPBYTE)&dwDummy,
    &dwDataSize );

    RegCloseKey(hkey);3.
    /*
    功能:得到98下的CUP使用率
    */
    inline double GetCPUusage98()
    { HKEY hkey;

    RegOpenKeyEx ( HKEY_DYN_DATA,
    "PerfStats\\StatData",
    0,KEY_ALL_ACCESS,
    &hkey ); 

    dwDataSize=sizeof(dwCpuUsage); 
    RegQueryValueEx ( hkey,
    "KERNEL\\CPUUsage",
    NULL,&dwType,
    (LPBYTE)&dwCpuUsage,
    &dwDataSize ); 

    RegCloseKey(hkey);  return dwCpuUsage;}4.结束使用:
    RegOpenKeyEx ( HKEY_DYN_DATA,
    "PerfStats\\StopStat",
    0,KEY_ALL_ACCESS,
    &hkey ); 

    dwDataSize=sizeof(dwDummy); RegQueryValueEx ( hkey,
    "KERNEL\\CPUUsage",
    NULL,&dwType,
    (LPBYTE)&dwDummy,
    &dwDataSize ); 

    RegCloseKey(hkey); Windows2000下获得CPU使用率:1:首先申明变量
    /
    // 为得到2000、NT、Xp下CPU使用率所用的变量
    #define SystemBasicInformation       0
    #define SystemPerformanceInformation 2
    #define SystemTimeInformation        3#define Li2Double(x) ((double)((x).HighPart) * 4.294967296E9 + (double)((x).LowPart))typedef struct
    {
        DWORD   dwUnknown1;
        ULONG   uKeMaximumIncrement;
        ULONG   uPageSize;
        ULONG   uMmNumberOfPhysicalPages;
        ULONG   uMmLowestPhysicalPage;
        ULONG   uMmHighestPhysicalPage;
        ULONG   uAllocationGranularity;
        PVOID   pLowestUserAddress;
        PVOID   pMmHighestUserAddress;
        ULONG   uKeActiveProcessors;
        BYTE    bKeNumberProcessors;
        BYTE    bUnknown2;
        WORD    wUnknown3;
    } SYSTEM_BASIC_INFORMATION;typedef struct
    {
        LARGE_INTEGER   liIdleTime;
        DWORD           dwSpare[76];
    } SYSTEM_PERFORMANCE_INFORMATION;typedef struct
    {
        LARGE_INTEGER liKeBootTime;
        LARGE_INTEGER liKeSystemTime;
        LARGE_INTEGER liExpTimeZoneBias;
        ULONG         uCurrentTimeZoneId;
        DWORD         dwReserved;
    } SYSTEM_TIME_INFORMATION;
    typedef LONG (WINAPI *PROCNTQSI)(UINT,PVOID,ULONG,PULONG);
    PROCNTQSI NtQuerySystemInformation;SYSTEM_PERFORMANCE_INFORMATION SysPerfInfo;
    SYSTEM_TIME_INFORMATION        SysTimeInfo;
    SYSTEM_BASIC_INFORMATION       SysBaseInfo;
    double                         dbIdleTime;
    double                         dbSystemTime;
    LONG                           status;LARGE_INTEGER                  liOldIdleTime = {0,0};
    LARGE_INTEGER                  liOldSystemTime = {0,0};double dCpuUsage;2:初始化函数中NtQuerySystemInformation = (PROCNTQSI)GetProcAddress(
    GetModuleHandle("ntdll.dll"),
    "NtQuerySystemInformation"
    );

    if (!NtQuerySystemInformation)
    {
    ASSERT ( 0 ) ;
    return FALSE ;
    }

    status = NtQuerySystemInformation(SystemBasicInformation,&SysBaseInfo,sizeof(SysBaseInfo),NULL);
    if (status != NO_ERROR)
    {
    ASSERT ( 0 ) ;
    return FALSE;
    }

    status = NtQuerySystemInformation(SystemTimeInformation,
    &SysTimeInfo,sizeof(SysTimeInfo),0);
    if (status!=NO_ERROR)
    {
    ASSERT ( 0 ) ;
    return FALSE;
    }

    // get new CPU's idle time
    status = NtQuerySystemInformation(SystemPerformanceInformation,
    &SysPerfInfo,sizeof(SysPerfInfo),NULL);
    if (status != NO_ERROR)
    {
    ASSERT ( 0 ) ;
    return FALSE;
    }

    liOldIdleTime = SysPerfInfo.liIdleTime;
    liOldSystemTime = SysTimeInfo.liKeSystemTime;3 :
    /*
    功能:得到2000、NT、XP下的CPU使用率
    */
    inline double GetCPUusageNT()
    {

    // get new system time
    status = NtQuerySystemInformation(SystemTimeInformation,
    &SysTimeInfo,sizeof(SysTimeInfo),0);
    if (status!=NO_ERROR)
    return -1;

    // get new CPU's idle time
    status = NtQuerySystemInformation(SystemPerformanceInformation,
    &SysPerfInfo,sizeof(SysPerfInfo),NULL);
    if (status != NO_ERROR)
    return -1;

    // if it's a first call - skip it
    if (liOldIdleTime.QuadPart != 0)
    {
    // CurrentValue = NewValue - OldValue
    dbIdleTime = Li2Double(SysPerfInfo.liIdleTime) - Li2Double(liOldIdleTime);
    dbSystemTime = Li2Double(SysTimeInfo.liKeSystemTime) - Li2Double(liOldSystemTime);

    // CurrentCpuIdle = IdleTime / SystemTime
    dbIdleTime = dbIdleTime / dbSystemTime;

    // CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors
    dbIdleTime = 100.0 - dbIdleTime * 100.0 / (double)SysBaseInfo.bKeNumberProcessors + 0.5;


    dCpuUsage = dbIdleTime ;
    }

    status = NtQuerySystemInformation(SystemTimeInformation,
    &SysTimeInfo,sizeof(SysTimeInfo),0);
    if (status!=NO_ERROR)
    return -1;

    // get new CPU's idle time
    status = NtQuerySystemInformation(SystemPerformanceInformation,
    &SysPerfInfo,sizeof(SysPerfInfo),NULL);
    if (status != NO_ERROR)
    return -1;

    // store new CPU's idle and system time
    liOldIdleTime = SysPerfInfo.liIdleTime;
    liOldSystemTime = SysTimeInfo.liKeSystemTime;

    return dCpuUsage ;
    }
      

  20.   

    http://202.117.64.21/csdn/vcmfc.chm不能下载了啊,其他的下载速度也很慢