VC/MFC 编程经验总结

VC/MFC 编程经验总结1URL:
http://expert.csdn.net/Expert/topic/2398/2398212.xml?temp=.3510706
|  在VC的使用过程中,每个人或多或少都会遇到一些麻烦,而这些问题可能其他人也同样遇到过,或许还没能解决。当你发现问题根结所在时,兴奋之余,欢迎你告诉他人同类问题的解决之道。
   大家如果有新的发现,请把你的编程经验收藏在这个帖子里吧!
   该贴会被放在本版面专题中http://www.csdn.net/Subject/297/index.shtm

   奖励办法:对于好的编程经验,贴主可以重新开零分贴,斑竹会将其加入精华或FAQ,奖励可用分(精华100分)、信誉分(FAQ主要问题解决人信誉分加5)

 
A: 主  题:  VC小技巧20个<ZT>
作  者:  codewarrior (会思考的草) 
等  级:   
信 誉 值:  103
所属论坛:  VC/MFC 基础类
问题点数:  0
回复次数:  11
发表时间:  2003-11-27 10:55:57
  
 
  
一、打开CD-ROM
mciSendString("Set cdAudio door open wait",NULL,0,NULL);


二、关闭CD_ROM
mciSendString("Set cdAudio door closed wait",NULL,0,NULL);


三、关闭计算机
OSVERSIONINFO OsVersionInfo; //包含操作系统版本信息的数据结构
OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&OsVersionInfo); //获取操作系统版本信息
if(OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
    //Windows98,调用ExitWindowsEx()函数重新启动计算机
    DWORD dwReserved;
    ExitWindowsEx(EWX_REBOOT,dwReserved); //可以改变第一个参数,实现注销用户、
    //关机、关闭电源等操作

    // 退出前的一些处理程序
}


四、重启计算机
typedef int (CALLBACK *SHUTDOWNDLG)(int); //显示关机对话框函数的指针
HINSTANCE hInst = LoadLibrary("shell32.dll"); //装入shell32.dll
SHUTDOWNDLG ShutDownDialog; //指向shell32.dll库中显示关机对话框函数的指针
if(hInst != NULL)
{
    //获得函数的地址并调用之
    ShutDownDialog = (SHUTDOWNDLG)GetProcAddress(hInst,(LPSTR)60);
    (*ShutDownDialog)(0);
}


五、枚举所有字体
LOGFONT lf;
lf.lfCharSet = DEFAULT_CHARSET; // Initialize the LOGFONT structure
strcpy(lf.lfFaceName,"");
CClientDC dc (this);

//Enumerate the font families
::EnumFontFamiliesEx((HDC) dc,&lf,
(FONTENUMPROC) EnumFontFamProc,(LPARAM) this,0);

//枚举函数
int CALLBACK EnumFontFamProc(LPENUMLOGFONT lpelf,LPNEWTEXTMETRIC lpntm,DWORD nFontType,long lparam)
{
    // Create a pointer to the dialog window
    CDay7Dlg* pWnd = (CDay7Dlg*) lparam;
    // add the font name to the list box

    pWnd ->m_ctlFontList.AddString(lpelf ->elfLogFont.lfFaceName);

    // Return 1 to continue font enumeration
    return 1;
}
其中m_ctlFontList是一个列表控件变量


六、一次只运行一个程序实例,如果已运行则退出
if( FindWindow(NULL,"程序标题")) exit(0);


七、得到当前鼠标所在位置
CPoint pt;
GetCursorPos(&pt); //得到位置


八、上下文菜单事件触发事件:OnContextMenu事件


九、显示和隐藏程序菜单
CWnd *pWnd=AfxGetMainWnd();
if(b_m) //隐藏菜单
{
    pWnd->SetMenu(NULL);
    pWnd->DrawMenuBar();
    b_m=false;
}
else
{
    CMenu menu;
    menu.LoadMenu(IDR_MAINFRAME); 显示菜单 也可改变菜单项
    pWnd->SetMenu(&menu);
    pWnd->DrawMenuBar();
    b_m=true;
    menu.Detach();
}
回复人: codewarrior(会思考的草) ( ) 信誉:103  2003-11-27 11:03:00  得分:0
 
 
  十一、窗口自动靠边程序演示
BOOL AdjustPos(CRect* lpRect)
{
    //自动靠边
    int iSX=GetSystemMetrics(SM_CXFULLSCREEN);
    int iSY=GetSystemMetrics(SM_CYFULLSCREEN);

    RECT rWorkArea;
    BOOL bResult = SystemParametersInfo(SPI_GETWORKAREA, sizeof(RECT), &rWorkArea, 0);

    CRect rcWA;
    if(!bResult)
    {
        //如果调用不成功就利用GetSystemMetrics获取屏幕面积
 rcWA=CRect(0,0,iSX,iSY);
    }
    else
 rcWA=rWorkArea;

    int iX=lpRect->left;
    int iY=lpRect->top;
    if(iX < rcWA.left + DETASTEP && iX!=rcWA.left)
    {
        //调整左
 //pWnd->SetWindowPos(NULL,rcWA.left,iY,0,0,SWP_NOSIZE);
 lpRect->OffsetRect(rcWA.left-iX,0);
 AdjustPos(lpRect);
 return TRUE;
    }
    if(iY < rcWA.top + DETASTEP && iY!=rcWA.top)
    {
 //调整上
 //pWnd->SetWindowPos(NULL ,iX,rcWA.top,0,0,SWP_NOSIZE);
 lpRect->OffsetRect(0,rcWA.top-iY);
 AdjustPos(lpRect);
 return TRUE;
    }
    if(iX + lpRect->Width() > rcWA.right - DETASTEP && iX !=rcWA.right-lpRect->Width())
    {
 //调整右
 //pWnd->SetWindowPos(NULL ,rcWA.right-rcW.Width(),iY,0,0,SWP_NOSIZE);
 lpRect->OffsetRect(rcWA.right-lpRect->right,0);
 AdjustPos(lpRect);
 return TRUE;
    }
    if(iY + lpRect->Height() > rcWA.bottom - DETASTEP && iY !=rcWA.bottom-lpRect->Height())
    {
 //调整下
     //pWnd->SetWindowPos(NULL ,iX,rcWA.bottom-rcW.Height(),0,0,SWP_NOSIZE);
 lpRect->OffsetRect(0,rcWA.bottom-lpRect->bottom);
 return TRUE;
    }
    return FALSE;
}
//然后在ONMOVEING事件中使用所下过程调用
CRect r=*pRect;
AdjustPos(&r);
*pRect=(RECT)r;


十二、给系统菜单添加一个菜单项
给系统菜单添加一个菜单项需要进行下述三个步骤:
首先,使用Resource Symbols对话(在View菜单中选择Resource Symbols...可以显示该对话)定义菜单项ID,该ID应大于

0x0F而小于0xF000;
其次,调用CWnd::GetSystemMenu获取系统菜单的指针并调用CWnd:: Appendmenu将菜单项添加到菜单中。下例给系统菜单添加

两个新的菜单项。
int CMainFrame:: OnCreate (LPCREATESTRUCT lpCreateStruct)
{
    …
    //Make sure system menu item is in the right range.
    ASSERT(IDM_MYSYSITEM<0xF000);
    //Get pointer to system menu.
    CMenu* pSysMenu=GetSystemMenu(FALSE);
    ASSERT_VALID(pSysMenu);
    //Add a separator and our menu item to system menu.
    CString StrMenuItem(_T ("New menu item"));
    pSysMenu->AppendMenu(MF_SEPARATOR);
    pSysMenu->AppendMenu(MF_STRING, IDM_MYSYSITEM, StrMenuItem);
    …
}


十三、运行其它程序
//1、运行EMAIL或网址
char szMailAddress[80];
strcpy(szMailAddress,"mailto:netvc@21cn.com");
ShellExecute(NULL, "open", szMailAddress, NULL, NULL, SW_SHOWNORMAL);

//2、运行可执行程序
WinExec("notepad.exe",SW_SHOW); //运行计事本


十四、动态增加或删除菜单
1、 增加菜单
//添加
CMenu *mainmenu;
mainmenu=AfxGetMainWnd()->GetMenu(); //得到主菜单
(mainmenu->GetSubMenu (0))->AppendMenu (MF_SEPARATOR);//添加分隔符
(mainmenu->GetSubMenu (0))->AppendMenu(MF_STRING,ID_APP_ABOUT,_T("Always on &Top")); //添加新的菜单项
DrawMenuBar(); //重画菜单

2、 删除菜单
//删除
CMenu *mainmenu;
mainmenu=AfxGetMainWnd()->GetMenu(); //得到主菜单
CString str ;
for(int i=(mainmenu->GetSubMenu (0))->GetMenuItemCount()-1;i>=0;i--) //取得菜单的项数。
{
    (mainmenu->GetSubMenu (0))->GetMenuString(i,str,MF_BYPOSITION);
    //将指定菜单项的标签拷贝到指定的缓冲区。MF_BYPOSITION的解释见上。
    if(str=="Always on &Top") //如果是刚才我们增加的菜单项,则删除。
    {
 (mainmenu->GetSubMenu (0))->DeleteMenu(i,MF_BYPOSITION);
  break;
    }
}


十、获取可执行文件的图标
HICON hIcon=::ExtractIcon(AfxGetInstanceHandle(),_T("NotePad.exe"),0);
if (hIcon &&hIcon!=(HICON)-1)
{
    pDC->DrawIcon(10,10,hIcon);
}
DestroyIcon(hIcon);
 
  主  题:  技巧
作  者:  fayifu (fayifu) 
等  级:   
信 誉 值:  100
所属论坛:  VC/MFC 基础类
问题点数:  1
回复次数:  3
发表时间:  2003-11-28 09:55:22
  
 
  
1.        如何激活当前屏幕保护程序
//激活当前屏幕保护程序, jingzhou xu
       PostMessage(WM_SYSCOMMAND,SC_SCREENSAVE,0);
2.        如何禁止/启用屏幕保护及电源管理
static UINT dss_GetList[] = {SPI_GETLOWPOWERTIMEOUT, SPI_GETPOWEROFFTIMEOUT, SPI_GETSCREENSAVETIMEOUT};
static UINT dss_SetList[] = {SPI_SETLOWPOWERTIMEOUT, SPI_SETPOWEROFFTIMEOUT, SPI_SETSCREENSAVETIMEOUT};
static const int dss_ListCount = _countof(dss_GetList);
l        禁止屏幕保护及电源管理
{
m_pValue = new int[dss_ListCount];
for (int x=0;x<dss_ListCount;x++)
{
//禁止屏幕保护及电源管理
VERIFY(SystemParametersInfo (dss_SetList[x], 0, NULL, 0));
}
delete[] m_pValue;
}
l        启用屏幕保护及电源管理
{
m_pValue = new int[dss_ListCount];
for (int x=0;x<dss_ListCount;x++)
{
//启用屏幕保护及电源管理
VERIFY(SystemParametersInfo (dss_SetList[x], m_pValue[x], NULL, 0));
}
delete[] m_pValue;
}
3.        如何激活和关闭IE浏览器
//激活并打开IE
void lounchIE()
{
  HWND h=FindWindowEx(NULL,NULL,NULL,
                      "Microsoft Internet Explorer") ;
  ShellExecute(h,"open","C://simple.html",
               NULL,NULL,SW_SHOWNORMAL);
}
//关闭IE及其它应用
void CloseIE()
{
  int app=BSM_APPLICATIONS;
  unsigned long  bsm_app=(unsigned long )app;
  BroadcastSystemMessage(BSF_POSTMESSAGE,&bsm_app,
                         WM_CLOSE,NULL,NULL);
}
4.        如何给树控件加入工具提示
l        首先给树控件加入TVS_INFOTIP属性风格,如下所示:
if (!m_ctrlTree.Create(WS_CHILD|WS_VISIBLE|
TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT|TVS_SHOWSELALWAYS|TVS_INFOTIP, //加入提示TVS_INFOTIP,jingzhou xu(树控件ID:100)
              CRect(0, 0, 0, 0), &m_wndTreeBar, 100))
       {
              TRACE0("Failed to create instant bar child/n");
              return -1;
       }
l        其次加入映射消息声明,如下所示:
afx_msg void OnGetInfoTip(NMHDR* pNMHDR,LRESULT* pResult);       //树控件上加入提示消息,jingzhou xu   
ON_NOTIFY(TVN_GETINFOTIP, 100, OnGetInfoTip)                           //树控件条目上加入提示,jingzhou xu
l        最后加入呼应涵数处理:
void CCreateTreeDlg::OnGetInfoTip(NMHDR* pNMHDR,
                                    LRESULT* pResult)
  {
  *pResult = 0;
  NMTVGETINFOTIP* pTVTipInfo = (NMTVGETINFOTIP*)pNMHDR;
  LPARAM itemData = (DWORD) pTVTipInfo->lParam;
  //对应每个条目的数据
  HTREEITEM hItem = pTVTipInfo->hItem;
  CString tip;
  HTREEITEM hRootItem = m_chassisTree.GetRootItem();
  if (hRootItem != pTVTipInfo->hItem)
  {
    tip = "树结点的提示";
  }
  else
  {
    tip = "树根上的提示";
  }
  strcpy(pTVTipInfo->pszText, (LPCTSTR) tip);
 }
5.        如何获取系统信息框的路径
#include <atlbase.h>
#define IDS_REG_KEY_MSINFO_PATH1 _T( "Software//Microsoft//Shared Tools//MSInfo" )
#define IDS_REG_KEY_MSINFO_PATH2 _T( "Software//Microsoft//Shared Tools Location" )
#define IDS_REG_VAL_MSINFO_PATH1 _T( "Path" )
#define IDS_REG_VAL_MSINFO_PATH2 _T( "MSInfo" )
#define IDS_MSINFO_EXE_NAME      _T( "MSInfo32.exe" )
//...
BOOL GetSysInfoPath( CString& strPath )
{       
    strPath.Empty();
    LPTSTR  pszPath = strPath.GetBuffer( MAX_PATH );
    CRegKey reg;
    DWORD   dwSize  = MAX_PATH;
    LONG    nRet    = reg.Open( HKEY_LOCAL_MACHINE, IDS_REG_KEY_MSINFO_PATH1, KEY_READ );
    //在注册表中寻找第一个"MSInfo32.exe"位置
    if ( nRet == ERROR_SUCCESS )
    {
        #if ( _MFC_VER >= 0x0700 )
            nRet = reg.QueryStringValue( IDS_REG_VAL_MSINFO_PATH1, pszPath, &dwSize );
        #else
            nRet = reg.QueryValue( pszPath, IDS_REG_VAL_MSINFO_PATH1, &dwSize );
        #endif
        reg.Close();
    }
    //如果第一次寻找失败,则进行第二次寻找
    if ( nRet != ERROR_SUCCESS )
    {
        nRet = reg.Open( HKEY_LOCAL_MACHINE, IDS_REG_KEY_MSINFO_PATH2, KEY_READ );
        if ( nRet == ERROR_SUCCESS )
        {
            #if ( _MFC_VER >= 0x0700 )
                reg.QueryStringValue( IDS_REG_VAL_MSINFO_PATH2, pszPath, &dwSize );
            #else
                reg.QueryValue( pszPath, IDS_REG_VAL_MSINFO_PATH2, &dwSize );
            #endif
            //路径名不包括EXE文件名
            if ( nRet == ERROR_SUCCESS )
                VERIFY( ::PathAppend( pszPath, IDS_MSINFO_EXE_NAME ) );
            reg.Close();
        }
    }
    strPath.ReleaseBuffer();
    strPath.FreeExtra();
    //检查文件是否有效.   
    return ::PathFileExists( strPath );
}
6.        如何直接运行一个资源中的程序
bool Run()
   {
       CFile f;
       char* pFileName = "Execution.exe";
       if( !f.Open( pFileName, CFile::modeCreate | CFile::modeWrite, NULL ) )
       {
              AfxMessageBox("Can not create file!");
              return 0;
       }
        CString path = f.GetFilePath();
       HGLOBAL hRes;
       HRSRC hResInfo;
     //获取应用实例
       HINSTANCE insApp = AfxGetInstanceHandle();
     //寻找EXE资源名
       hResInfo = FindResource(insApp,(LPCSTR)IDR_EXE4,"EXE");
       hRes = LoadResource(insApp,hResInfo );   // Load it
       DWORD dFileLength = SizeofResource( insApp, hResInfo );  //计算EXE文件大小
       f.WriteHuge((LPSTR)hRes,dFileLength);  //写入临时文件
       f.Close();
       HINSTANCE HINSsd = ShellExecute(NULL, "open",path, NULL, NULL, SW_SHOWNORMAL);> //运行它. 
       return 1;
}

 
7.        如何遍历整个目录
#include <windows.h>
#include <shlobj.h>
//浏览目录.
void BrowseFolder( void )
{
       TCHAR path[MAX_PATH];
       BROWSEINFO bi = { 0 };
       bi.lpszTitle = ("递归调用所有目录");
       LPITEMIDLIST pidl = SHBrowseForFolder ( &bi );
       if ( pidl != 0 )
       {
              //获取目录路径
              SHGetPathFromIDList ( pidl, path );
              //设置为当前路径
              SetCurrentDirectory ( path );
              //搜索所有子目录
              SearchFolder( path );
              //释放内存
              IMalloc * imalloc = 0;
              if ( SUCCEEDED( SHGetMalloc ( &imalloc )) )
              {
                     imalloc->Free ( pidl );
                     imalloc->Release ( );
              }
}
//搜索其下所有子目录及文件.
void SearchFolder( TCHAR * path )
{
              WIN32_FIND_DATA FindFileData;
              HANDLE               hFind;
              TCHAR   filename[ MAX_PATH + 256 ];
              TCHAR   pathbak[ MAX_PATH ];
              //复制初始用户选择目录
              strcpy( pathbak, path );
              //寻找第一个文件
              hFind = FindFirstFile ( "*.*", &FindFileData );
              //搜索所有文件及子目录
              do
              {
                     if ( hFind != INVALID_HANDLE_VALUE )
                     {
                            //如果是当前目录或父目录,跳过
                            if ( ! ( strcmp( FindFileData.cFileName, "." ) ) || ! ( strcmp( FindFileData.cFileName, ".." ) ) )
                            {
                                   continue;
                            }
                            //恢复初始用户选择目录
                            strcpy( path, pathbak );
                            //列出所有发现的文件
                            sprintf( path, "%s//%s", path, FindFileData.cFileName );
                            //如果SetCurrentDirectory成功的话,则它是一个目录,递归调用继续搜索子目录
                            if ( ( SetCurrentDirectory( path ) ) )
                            {
                                   SearchFolder( path );
                            }
                     //插入文件及路径名到列表框m_listbox_hwnd中
                    SendMessage( m_listbox_hwnd, LB_ADDSTRING, 0, path ); //<--INSERT WHAT YOU WANT DONE HERE!
                     }
              }
              while ( FindNextFile ( hFind, &FindFileData ) && hFind != INVALID_HANDLE_VALUE );
              FindClose ( hFind );
}
8.        如何禁止/启用系统热键
bool bOld;
l        禁止系统热键
//屏蔽掉系统键
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING,true,&bOld,SPIF_UPDATEINIFILE);
l        启用系统热键
//恢复系统热键   
SystemParametersInfo(SPI_SETSCREENSAVERRUNNING,false,&bOld,SPIF_UPDATEINIFILE);
9.        如何隐藏/显示WINDOWS系统任务栏
l        隐藏系统任务栏
//隐藏WINDOWS系统任务栏
       ::ShowWindow (::FindWindow("Shell_TrayWnd",NULL),SW_HIDE);
l        显示系统任务栏
//恢复WINDOWS系统任务栏正常显示
::ShowWindow (::FindWindow("Shell_TrayWnd",NULL),SW_SHOW);
T: 各位大侠,还是读写文件问题,再百分相送 
Q: 各位大侠,我在VC里面编程
想把一个文件里面的所有大写字符都转换成小写
用打开一个文件读写的方法

 FILE * ff;
 ff=fopen("a.txt","w");
 if(ff == NULL) return 0;
 char c;
 while(!feof(ff)){
  c=fgetc(ff);
                  fseek(ff,-1,SEEK_CUR);
                  fputc(tolower(c),ff);
                  fseek(ff,1,SEEK_CUR);

 }
 fclose(ff);
是个死循环了
如何能不用中间文件
通过文件位置指针
完成一个文件的读写??
望各位指点迷津
问题解决立刻给分
 
A: 害我睡不成觉,赔!
我调试通过了。使用内存影像文件
#include "stdafx.h"
#include "windows.h"
int main(int argc, char* argv[])
{
 HANDLE hFile = CreateFile("J://a.txt",
  GENERIC_WRITE | GENERIC_READ,
  FILE_SHARE_READ,
  NULL,
  OPEN_ALWAYS,
  FILE_FLAG_SEQUENTIAL_SCAN,
  NULL);
 int iLen=GetFileSize(hFile,NULL)+1;
 HANDLE hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READWRITE, 0, iLen, NULL);
 // 释放文件内核对象
 CloseHandle(hFile);
 __int64 qwFileOffset = 0;
 PBYTE pbFile = (PBYTE)MapViewOfFile(hFileMapping,FILE_MAP_ALL_ACCESS,
  (DWORD)(qwFileOffset>>32), (DWORD)(qwFileOffset&0xFFFFFFFF), iLen);
 strcpy((char*)(pbFile+qwFileOffset),_strlwr( _strdup( (char*)(pbFile+qwFileOffset))));
 UnmapViewOfFile(pbFile);
 CloseHandle(hFileMapping);
 
 return 0;
}

 
T: 一个文件异常(CFileException)的问题,在线等待! 
Q:  try
 {
  CFile::Remove(filename);
 }
 catch (CFileException& Exception)
 {
  switch(Exception.m_cause)
  {
  case CFileException::accessDenied:
   TRACE("Access denied!/n");
   return FALSE;
  default:
   TRACE("Remove default Exception!/n");
   return FALSE;
  }
 }

      我在一个程序要删除另一个程序正在读的文件, 用上面的方法捕获异常, 为什么总是捕获不到, 删除文件是程序抛出 Abnormal program exception, 的C++ runtime error提示, 在TRACE中能看到windows给出的accessDenied异常, 但我的程序总是捕获不到,为什么?
 
A: void CDelFileDlg::OnButton1()
{
 // TODO: Add your control notification handler code here
 try
 {
  CFile::Remove("E://Program Files//UltraEdit//UEDIT32.EXE");
 }
 catch(CFileException* e)
 {
  switch(e->m_cause)
  {
  case CFileException::accessDenied:
   TRACE("Access denied!/n");
   return ;
  default:
   TRACE("Remove default Exception!/n");
   return ;
  }
 }
}


我试过他们的,确实不行
不过我现在的行:)
 
T: DEBUG模式下编译、链接、运行都没问题。可是在Release模式下,就会出现非法操作??? 
Q: 这个问题很复杂,我都有点不知道该怎么描述它。所以不求你们能给我一个精确的答案,我只想要一个解决问题的思路。因为我以前从未遇到过这种情况。

问题是这样的:

我的程序已经写完了,在DEBUG版本下编译、链接、运行都没问题。现在我要发布这个程序,当然得在Release模式下编译它。这时,编译、连接都没问题,没有任何警告与错误。可是当它运行起来的时侯,如果我执行了一个特定的操作:程序会在系统托盘里添加一个图标,鼠标右击这个图标会出现一个菜单,当单击其中一个菜单项时,程序就会出现非法操作。我把对这个命令消息的处理过程清空,即什么操作都不执行,只是一个空函数。它也会出现非法操作。可是,如果在DEBUG模式下,无论怎样都不会出错(不管函数内有没有代码)。

这个问题真是有些棘手,因为在Release模式下没法调试,要调试的话,也只能是汇编级调试,我不会汇编。现在的问题是,我该如何着手从那个方向去解决这个问题呢?
A: 这个问题很复杂,我都有点不知道该怎么描述它。所以不求你们能给我一个精确的答案,我只想要一个解决问题的思路。因为我以前从未遇到过这种情况。

问题是这样的:

我的程序已经写完了,在DEBUG版本下编译、链接、运行都没问题。现在我要发布这个程序,当然得在Release模式下编译它。这时,编译、连接都没问题,没有任何警告与错误。可是当它运行起来的时侯,如果我执行了一个特定的操作:程序会在系统托盘里添加一个图标,鼠标右击这个图标会出现一个菜单,当单击其中一个菜单项时,程序就会出现非法操作。我把对这个命令消息的处理过程清空,即什么操作都不执行,只是一个空函数。它也会出现非法操作。可是,如果在DEBUG模式下,无论怎样都不会出错(不管函数内有没有代码)。

这个问题真是有些棘手,因为在Release模式下没法调试,要调试的话,也只能是汇编级调试,我不会汇编。现在的问题是,我该如何着手从那个方向去解决这个问题呢?
 
T: [VC新手]问矢量轮廓描述与填充算法 
Q: 请问 Windows 下矢量字体是如何描述的,如以 TrueType 字体为例,其格式如何?

我要做的应用是最终控制物理器件的运动轨迹走出汉字(大小可变)的外形轮廓,然后以水平、垂直或45°方向的直线填充(密度可调),请问该用什么算法实现?

由于我对矢量格式一无所知,希望大家能教以方法,或提供基础性资料,网址亦可
A: 要实践你的功能,不一定要用GetPath,我的思路是,先在Form上画出你需要的字,
然后用扫描线的方法复制到你的设备上,设备只需用MoveTo及LineTo

void __fastcall TForm1::Button1Click(TObject *Sender)
{
     String ch="噗"; //可以多个字符
     Canvas->Font->Name="宋体";
     Canvas->Font->Color=clBlack;
     Canvas->Font->Size=40;  
     Canvas->TextOut(100,100,ch);  
     int w=Canvas->TextWidth(ch);
     int h=Canvas->TextHeight(ch);
    TColor c,oldc;
    for(int j=0;j<h;j++)
     {
      oldc=c=clWhite;
      for(int i=0;i<w;i++)
        {
            c=Canvas->Pixels[100+i][100+j];
            if (c!=oldc)
             {
                if (c==clBlack)
                    Canvas->MoveTo(300+i,100+j);  //在你的设备上MoveTo
                  else
                    Canvas->LineTo(300+i,100+j); //在你的设备上LineTo
                oldc=c;
             }
        }
      }


}
 
T: 如何在主程序中释放DLL中new的内存? 
Q: 兄弟在主程序中用loadlibrary加载了一个DLL,然后在调用该DLL的一个函数时,返回在该函数中使用new操作符得到的一个内存指针,在主程序中使用完该指针后用delete释放时出现debug错误,这怎么办?
 
A: 3:Dll分配的内存块,应用程序释放,结果报异常。
    用GlobalAlloc()代替new, 用GlobalFree() 代替delete就不会出错了
    其实还有一个办法,就是把dll的Settings的C/C++选项卡的Code Generation的Use Run-time liberary改成Debug Multithreaded DLL,在Release版本中改成Multithreaded DLL,就可以直接使用new和delete了,没问题
    比较规范点的做法一般是DLL分配的内存由DLL释放。在DLL中加一个函数释放内存不是更好吗。

给分吧,呵呵
 
T: mfc dll如何导出类 
Q: 我要在mfc dll中,非mfc 扩展dll,也不是非mfc dll,导出一个类,如何实现呀
A: 呵呵,想不到我的东西也要被别人广为传抄了:
http://expert.csdn.net/Expert/topic/2514/2514628.xml?temp=.4149897

导出类很简单的
在你的DLL中Alt+F7中有一个C/C++中preprocessor definitions编辑框添加AAA_EXPORTS定义,然后在头文件类定义之前添加
#ifdef AAA_EXPORTS
#define AAA_API __declspec(dllexport)
#else
#define AAA_API __declspec(dllimport)
#endif
然后在你的类的声明前添加AAA_API ,就象上面一样,在主工程中包括这个头文件,主工程中在ALT+F7的LINK选项卡添加该DLL的.LIB文件。OK
T: 有人做过线形算法吗?
Q: 有人做过线形算法吗?欢迎提供详细思路
A: 这些代码你研究一下
WINNT下,可以用以下方式创建画笔

       LOGBRUSH brush;

       brush.lbColor=DrawColor;

       brush.lbStyle=BS_SOLID;

mPen.CreatePen(PS_GEOMETRIC|PS_USERSTYLE|PS_ENDCAP_FLAT,(int)LineWide,&brush,i,PenStyle);

 

Win98中,给DC设置合适的笔宽,选择实线,下面函数可以根据PenStyle数组给定长度值画直线。如果画曲线或者折线,需要把曲线离散成直线段,根据上次画线返回值确定本次画线的起始值,就可以了

#include "math.h"

DWORD   PenStyle[16] = {0,0,0,0,0,0,0,0,

0,0,0,0,0,0,0,0};

typedef struct xyz {

       double x;

       double y;

       double z;

} XYZ,*PXYZ,**PPXYZ;

 

//按照PenStyle[]画一条从p1点到p2点的直线

//例如PenStyle[0]=5,PenStyle[1]=2表示按照长度为5的实线、长度为2的间隔形成的线型画线

//_____  _____  _____  _

//并且指定从线型的何处画,例如iStart=6从Penstyle[1]处的第二个空格开始画

//iStart取值范围为0到一个线型的总长度-1

//返回值:线型总长度与剩余最后一段线长度之差,表示下一次画线应该指定的从何处开始画

int DrawLineA(CDC* pDC,POINT p1,POINT p2,int iStart)

{

       int i=0;

       int iEnd=0;//返回值,表示最后一段不完全的线段的长度

       //计算直线长度

       double dDistance=sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));

       int iLineType=0;//线型的长度

       if(dDistance<2)

       {

              for(i=0;i<16;i++)

              {

                     if(PenStyle[i]==0)break;

                     iLineType+=PenStyle[i];

              }

              iEnd=(int(iStart-dDistance))%iLineType;

              if(iEnd<0)iEnd+=iLineType;

              return iEnd;

       }

       double ddltx[16]={0,0,0,0,//每一段线型的x距离

              0,0,0,0,

              0,0,0,0,

              0,0,0,0};

       double ddlty[16]={0,0,0,0,//每一段线型的y距离

              0,0,0,0,

              0,0,0,0,

              0,0,0,0};

       double dXScale=(p2.x-p1.x)/dDistance;//x方向长度和总长度比例

       double dYScale=(p2.y-p1.y)/dDistance;//y方向长度和总长度比例

       //计算每一段线型的x、y距离及线型的长度

       for(i=0;i<16;i++)

       {

              if(PenStyle[i]==0)break;

              ddltx[i]=PenStyle[i]*dXScale;

              ddlty[i]=PenStyle[i]*dYScale;

              iLineType+=PenStyle[i];

       }

       iEnd=(int(dDistance+iStart))%iLineType;

       if(iEnd<0)iEnd+=iLineType;

      

       XYZ pp={0,0,0};//第一段之前的完整线型开始点

       pDC->MoveTo(p1);

       int iLength=-iStart;//已经画的线段的长度

       pp.x=iLength*dXScale+p1.x;

       pp.y=iLength*dYScale+p1.y;

       for(;;)

       {

              for(i=0;i<16;i++)

              {

                     if(PenStyle[i]==0)break;

                     pp.x+=ddltx[i];

                     pp.y+=ddlty[i];

                     iLength+=PenStyle[i];

                     if(i%2==0)

                     {

                            if(iLength>0)

                            {

                                   if(iLength<dDistance)

                                   {

                                          pDC->LineTo(pp.x,pp.y);

                                   }

                                   else

                                   {

                                          pDC->LineTo(p2);

                                          return iEnd;

                                   }

                            }

                     }else

                     {

                            if(iLength>0)

                            {

                                   if(iLength<dDistance)

                                   {

                                          pDC->MoveTo(pp.x,pp.y);

                                   }

                                   else

                                   {

                                          pDC->MoveTo(p2);

                                          return iEnd;

                                   }

                            }

                     }

              }

       }

       return iEnd;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值