初学vc时得一些记录(不是本人)

作者在 2010-04-17 14:16:41 发布以下内容

////////////////////////////////////////////////////////////
 //得到屏幕的尺寸大小
 HWND hWnd;
 CRect Rect;
 hWnd = ::GetDesktopWindow();
 ::GetClientRect(hWnd, &Rect);

////////////////////////////////////////////////////////////
//添加托盘
void CWorkSheetTrayDlg::AddTaskBarIcon()
{
 m_Nid.cbSize = sizeof(m_Nid);
 m_Nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
 m_Nid.hIcon=(HICON)LoadImage(AfxGetInstanceHandle(),
   MAKEINTRESOURCE(IDI_SysIcon),IMAGE_ICON,16,16,NULL);

 //加载系统缺省图标
 strcpy(m_Nid.szTip,"潍坊检修申请管理系统");
 //提示字符
 m_Nid.uCallbackMessage=WM_USER + 10;
 m_Nid.uID = 10;
 m_Nid.hWnd=m_hWnd;
 Shell_NotifyIcon(NIM_ADD,&m_Nid);
}

//删除托盘
void CWorkSheetTrayDlg::DeleteTaskBarIcon()
{
// NOTIFYICONDATA m_Nid;
 m_Nid.cbSize=sizeof(m_Nid);
 m_Nid.uID=10;
 m_Nid.hWnd=m_hWnd;
 Shell_NotifyIcon(NIM_DELETE,&m_Nid);
}

////////////////////////////////////////////////////////////////////

 //将窗口移动到屏幕中央显示
 CenterWindow(GetDesktopWindow());

////////////////////////////////////////////////////////////////////
 //得到工作路径
 char Path[512];
 CString RunPath;
 GetCurrentDirectory(512, Path);
 RunPath.Format("%s", Path);
 //得到可执行文件目录
 CString RunPath;
 int PathLength;
 ::GetModuleFileName(::AfxGetInstanceHandle(), RunPath.GetBuffer(1024), 1024);
 RunPath.ReleaseBuffer(-1);

 for (PathLength=RunPath.GetLength()-1; PathLength>=0; PathLength--)
 {
  if (RunPath.GetAt(PathLength) == '\\')
   break;
 }
 CString FileName, CurPath;
 CurPath = RunPath.Left(PathLength);
 FileName = RunPath.Mid(PathLength+1);
// AfxMessageBox(RunPath+_T("--")+CurPath+_T("--")+FileName, MB_ICONINFORMATION);
/////////////////////////////////////////////////////////////////////////
设置标题
BOOL CMyApp::InitInstance()中加m_pMainWnd->SetWindowText(_T("你要写的名字 "));

//////////////////////////////////////////////////////////////////
 //窗口最大化
 m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
 m_pMainWnd->UpdateWindow();

////////////////////////////////////////////////////////////////// 
 //扩展风格:使 List 带有 整行选择、表格、整行预选 功能
 DWORD dwStyleEx;
 dwStyleEx = LVS_EX_FULLROWSELECT | LVS_REPORT |  LVS_EX_ONECLICKACTIVATE;
 m_GndDzStatusList.SetExtendedStyle( dwStyleEx );
//////////////////////////////////////////////////////////////////
 //设置光标
 SetCursor(AfxGetApp()->LoadCursor(IDC_CrossArrow));
 
 //菜单加对勾
 pCmdUI->SetCheck(m_bIsDrawLine);

 //颜色
 pDC->SetTextColor(RGB(0, 0, 0));
 //背景颜色
 pDC->SetBkColor(RGB(192, 255, 192));
 
 //得到CString的长度
 CClientDC dc(this);
 CString sTextWord;

 CSize cSize;
 cSize = dc.GetTextExtent(m_strBaseWord[m_BaseWordID].TextWord,   
  m_strBaseWord[m_BaseWordID].TextWord.GetLength());

 //得到当前字体的信息
 TEXTMETRIC tm;
 CClientDC dc(this);
 dc.GetTextMetrics(&tm);
 
 //创建光标宽度,高度
 CreateSolidCaret(tm.tmAveCharWidth/8, tm.tmHeight);
 //设置光标
 SetCaretPos(m_pPoint);
 //显示光标
 ShowCaret();
//////////////////////////////////////////////////////////////////
 AfxMessageBox(_T("删除 ") + Purpose + _T(" 失败!"), MB_ICONSTOP);
 //选中一项
 m_ExpenseList.SetSelectionMark(0);
 //插入首一项
 m_ExpenseList.InsertItem(nIndex, m_Purpose, 0);

 //自动选中一项
 m_GndDzStatusList.SetItemState(nItem, LVIS_SELECTED, LVIS_SELECTED);
 
 //自动滚动确保选中项能见
 m_ContractList.EnsureVisible(nIndex, 1);

 //删除CString中的%号
 CString sString.Remove('%');

 //防止添加Box重复
 while (pStockMsgSet->IsEOF() == FALSE)
 {
  if ( m_StockTypeBox.FindStringExact(-1, pStockMsgSet->m_StockType) < 0 )
   m_StockTypeBox.AddString(pStockMsgSet->m_StockType);
  pStockMsgSet->MoveNext();
 }

 //打开数据库
 TRY
 {
  pStationNameSet->Open();
 }
 CATCH(CDBException, e)
 {
  AfxMessageBox("不能打开[StationName]表, \n  导出厂站失败!");
  delete pStationNameSet;
  return FALSE;
 }
 END_CATCH

//////////////////////////////////////////////////////////////////

 //取当前目录
 char Path[255];
 GetCurrentDirectory(255, Path);

//////////////////////////////////////////////////////////////////
 //用对话框找文件
 CString sSelectPathName;
 CString sSelectName;
 CString sSelectExt;

 CFileDialog dlg(TRUE);
 dlg.m_ofn.Flags = OFN_NOCHANGEDIR;
 dlg.m_ofn.lpstrFilter = "Micrsoft Acess 数据库  (*.mdb)\0*.mdb\0\0";
 if (dlg.DoModal() == IDCANCEL)
  return FALSE;

 //创建 ODBC ,选择数据库

 sSelectPathName = dlg.GetPathName();
 sSelectName     = dlg.GetFileTitle();
 sSelectExt  = dlg.GetFileExt();

 if (sSelectExt.CompareNoCase("mdb") != 0)
 {
  AfxMessageBox("所选文件扩展名必须是 .mdb ! \n  请重新选 择数据库。");
  return FALSE;
 }

//////////////////////////////////////////////////////////////////

 //显示盘符
 void CFileMakerView::FillDriveInfo()
 {
  DWORD dwDrives;
  char a;
  CString DriveName;

  dwDrives = GetLogicalDrives();

  a = 'A';

  while (dwDrives > 0)
  {
   if (dwDrives % 2 == 1)
   {
    DriveName.Format("%c", a);
    GetTreeCtrl().InsertItem(DriveName,  m_nImageClose, m_nImageOpen, TVI_ROOT, TVI_LAST);
   }

   a++;
   dwDrives /= 2;
  }
 }

//////////////////////////////////////////////////////////////////

 //判该程序是否运行(BOOL CMakeSheetApp::InitInstance())

 HANDLE Handle;
 Handle = CreateMutex(NULL, TRUE, _T("MakeSheet3.0"));
 if (Handle == NULL)
  return FALSE;
 if (GetLastError() == ERROR_ALREADY_EXISTS)
 {
  AfxMessageBox("MakeSheet3.0已运行!", MB_ICONSTOP);
  return FALSE;
 }

//////////////////////////////////////////////////////////////////

 //得到System所在目录(为与WindowsNT兼容) 
 char  cSysDir[100], cFileName[] = "\\odbcjt32.dll";
 GetSystemDirectory(cSysDir, 100);
 //连接两个字符串
 strcat(cSysDir, cFileName);

//////////////////////////////////////////////////////////////////

 //给对话框加上位图
 
  //在头文件中定义(public)
 CDibApi m_BackBmp;

 BOOL CDeviceQueryDlg::OnInitDialog()
 {
  m_BackBmp.OpenBmp(".\\位图.bmp");
  m_BackBmp.InitDIBData();
 }

 void CDeviceQueryDlg::OnPaint()
 {
  m_BackBmp.DrawDIB(&dc, 0, 0);
 }
 2.链表
自已定义一个.h文件,然后,在里面加入类的定义
class CPartA : public CObject
{
public:
 CPartA() {}
 virtual ~CPartA() {}

 int m_a;
 int m_b;
 CString m_c;
 int m_d;  
};

typedef CTypedPtrList<CObList, CPartA*> CPartAList;//重点在这儿

class CInfoA
{
public:
 CInfoA() {}
 virtual ~CInfoA();

 BOOL AddData(int a, int b, CString c, int d); //用于加入数据的
 
 CPartA  m_objects;
};
在.cpp里

CInfoA的析构
CInfoA::~CInfoA()
{
 POSITION pos = m_objects.GetHeadPosition();

 while (pos != NULL)
  delete m_objects.GetNext(pos);
}

//加入到链表
CInfoA::AddData(int a, int b, CString c, int d)
{
 CPartA* pPart = new CPartA();

 pPart->m_a = a;
 pPart->m_b = b;
 pPart->m_c = c;
 pPart->m_d = d;
 
 m_objects.AddTail(pPart);

 return TRUE;
}

自已来引申,一定对你有用处的,当你在程序中要用到这个链表时
你只要在.h里定义
CInfoA  m_InfoA
在.cpp里
m_Info.AddPart(1, 2, "ddd", 3);
就可以加入了

3.遍历这个链表
你在程序中的函数加入下面的语句即可

POSITION pos;

pos = m_InfoA.m_objects.GetHeadPosition();
while (pos != NULL)
{
 CPartA* pPart = m_InfoA.m_objects.GetNext(pos);
         if (pPart->m_a != 0)
            ........
}
 
防止窗口闪烁的方法

1、将Invalidate()替换为InvalidateRect()。

  Invalidate()会导致整个窗口的图象重画,需要的时间比较长,而InvalidateRect()仅仅重画Rect区域内的内容,所以所需时间会少一些。虫虫以前很懒,经常为一小块区域的重画就调用Invalidate(),不愿意自己去计算需要重画的Rect,但是事实是,如果你确实需要改善闪烁的情况,计算一个Rect所用的时间比起重画那些不需要重画的内容所需要的时间要少得多。

2、禁止系统搽除你的窗口。

  系统在需要重画窗口的时候会帮你用指定的背景色来搽除窗口。可是,也许需要重画的区域也许非常小。或者,在你重画这些东西之间还要经过大量的计算才能开始。这个时候你可以禁止系统搽掉原来的图象。直到你已经计算好了所有的数据,自己把那些需要搽掉的部分用背景色覆盖掉(如:dc.FillRect(rect,&brush);rect是需要搽除的区域,brush是带背景色的刷子),再画上新的图形。要禁止系统搽除你的窗口,可以重载OnEraseBkgnd()函数,让其直接返回TRUE就可以了。如

BOOL CMyWin::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
//return CWnd::OnEraseBkgnd(pDC);//把系统原来的这条语句注释掉。
}

  3、有效的进行搽除。

  搽除背景的时候,不要该搽不该搽的地方都搽。比如,你在一个窗口上放了一个很大的Edit框,几乎占了整个窗口,那么你频繁的搽除整个窗口背景将导致Edit不停重画形成剧烈的闪烁。事实上你可以CRgn创建一个需要搽除的区域,只搽除这一部分。如

GetClientRect(rectClient);
rgn1.CreateRectRgnIndirect(rectClient);
rgn2.CreateRectRgnIndirect(m_rectEdit);
if(rgn1.CombineRgn(&rgn1,&rgn2,RGN_XOR) == ERROR)//处理后的rgn1只包括了Edit框之外的客户区域,这样,Edit将不会被我的背景覆盖而导致重画。
{
ASSERT(FALSE);
return ;
}
brush.CreateSolidBrush(m_clrBackgnd);
pDC->FillRgn(&rgn1,&brush);
brush.DeleteObject();

  注意:在使用这个方法的时候要同时使用方法二。别忘了,到时候又说虫虫的办法不灵。

  4、使用MemoryDC先在内存里把图画好,再复制到屏幕上。

  这对于一次画图过程很长的情况比较管用。毕竟内存操作比较快,而且复制到屏幕又是一次性的,至少不会出现可以明显看出一个东东从左画到右的情况。

void CMyWin::OnPaint()
{
CPaintDC dc1(this); // device context for painting
dcMemory.CreateCompatibleDC(&dc1);
CBitmap bmp;//这里的Bitmap是必须的,否则当心弄出一个大黑块哦。
bmp.CreateCompatibleBitmap(&dc1,rectClient.Width(),rectClient.Height());
dcMemory.SelectObject(&bmp);

//接下来你想怎么画就怎么画吧。
//dcMemory.FillRect(rectClient,&brush);

dc1.BitBlt(0,0,rectClient.Width(),rectClient.Height(),&dcMemory,0,0,SRCCOPY);
dcMemory.DeleteDC();
// Do not call CWnd::OnPaint() for painting messages
}
 
Vc里只提供了一个rand()随机数取0--32767(我刚学VC不久,很多东西都不懂,也许还有其他的随机函数)
我写的random():
全局变量:
unsigned long holdrand1;


void srand1(unsigned long seed)
//seed should be equal a random
//for example:=(unsigned)time( NULL )
{
 holdrand1 = seed;
}

unsigned long random(unsigned long Range)
//0<=return value<Range
{
 holdrand1 = (holdrand1 * 73279687L
            + 302460951874L) >> 2;
 return holdrand1 % Range;
}


使用CCtrlList应注意的问题:
1、每插入一个Item后,都应该Update();
2、Item的序号是从0,开始的,不是从1;
3、如果要插入SubItem,应该使用SetItemText;
在写自己的generic类的时候,在头文件的最后一个“}”之后,
应该加上一个";",要不,VC在编译的时候,提示的错误信息
会让你不知所云。不信你就试试。^__^

转贴一篇关于串口通讯的:

作者: 佚名
在WIN32下是不建议对端口进行操作的,在WIN32中所有的设备都被看成是文件,串行口也不例外也是作为文件来进行处理的。这是我的一份关于串口编程的读书笔记,对于使用VC进行编程的同行应该有一定的帮助。
1.打开串口:
在Window 95下串行口作为文件处理,使用文件操作对串行口进行处理。
使用CreateFile()打开串口,CreateFile()将返回串口的句柄。
HANDLE CreateFile(
LPCTSTR lpFileName, // pointer to name of the file
DWORD dwDesiredAccess, // access (read-write) mode
DWORD dwShareMode, // share mode
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes
DWORD dwCreationDistribution, // how to create
DWORD dwFlagsAndAttributes, // file attributes
HANDLE hTemplateFile // handle to file with attributes to copy
);
lpFileName: 指明串口制备,例:COM1,COM2
dwDesiredAccess: 指明串口存取方式,例:GENERIC_READ|GENERIC_WRITE
dwShareMode: 指明串口共享方式
lpSecurityAttributes: 指明串口的安全属性结构,NULL为缺省安全属性
dwCreateionDistribution: 必须为OPEN_EXISTIN
dwFlagAndAttributes: 对串口唯一有意义的是FILE_FLAG_OVERLAPPED
hTemplateFile: 必须为NULL


2.关闭串口:
CloseHandle(hCommDev);

3.设置缓冲区长度:
BOOL SetupComm(
HANDLE hFile, // handle of communications device
DWORD dwInQueue, // size of input buffer
DWORD dwOutQueue // size of output buffer
);

4.COMMPROP结构:
可使用GetCommProperties()取得COMMPROP结构,COMMPROP结构中记载了系统支持的各项设置。
typedef struct _COMMPROP { // cmmp
WORD wPacketLength; // packet size, in bytes
WORD wPacketVersion; // packet version
DWORD dwServiceMask; // services implemented
DWORD dwReserved1; // reserved
DWORD dwMaxTxQueue; // max Tx bufsize, in bytes
DWORD dwMaxRxQueue; // max Rx bufsize, in bytes
DWORD dwMaxBaud; // max baud rate, in bps
DWORD dwProvSubType; // specific provider type
DWORD dwProvCapabilities; // capabilities supported
DWORD dwSettableParams; // changeable parameters
DWORD dwSettableBaud; // allowable baud rates
WORD wSettableData; // allowable byte sizes
WORD wSettableStopParity; // stop bits/parity allowed
DWORD dwCurrentTxQueue; // Tx buffer size, in bytes
DWORD dwCurrentRxQueue; // Rx buffer size, in bytes
DWORD dwProvSpec1; // provider-specific data
DWORD dwProvSpec2; // provider-specific data
WCHAR wcProvChar[1]; // provider-specific data
} COMMPROP;

dwMaxBaud:
BAUD_075 75 bps
BAUD_110 110 bps
BAUD_134_5 134.5 bps
BAUD_150 150 bps
BAUD_300 300 bps
BAUD_600 600 bps
BAUD_1200 1200 bps
BAUD_1800 1800 bps
BAUD_2400 2400 bps
BAUD_4800 4800 bps
BAUD_7200 7200 bps
BAUD_9600 9600 bps
BAUD_14400 14400 bps
BAUD_19200 19200 bps
BAUD_38400 38400 bps
BAUD_56K 56K bps
BAUD_57600 57600 bps
BAUD_115200 115200 bps
BAUD_128K 128K bps
BAUD_USER Programmable baud rates available

dwProvSubType:
PST_FAX 传真设备
PST_LAT LAT协议
PST_MODEM 调制解调器设备
PST_NETWORK_BRIDGE 未指定的网桥
PST_PARALLELPORT 并口
PST_RS232 RS-232口
PST_RS422 RS-422口
PST_RS423 RS-432口
PST_RS449 RS-449口
PST_SCANNER 扫描仪设备
PST_TCPIP_TELNET TCP/IP Telnet协议
PST_UNSPECIFIED 未指定
PST_X25 X.25标准

dwProvCapabilities
PCF_16BITMODE 支持特殊的16位模式
PCF_DTRDSR 支持DTR(数据终端就绪)/DSR(数据设备就绪)
PCF_INTTIMEOUTS 支持区间超时
PCF_PARITY_CHECK 支持奇偶校验
PCF_RLSD 支持RLSD(接收线信号检测)
PCF_RTSCTS 支持RTS(请求发送)/CTS(清除发送)
PCF_SETXCHAR 支持可设置的XON/XOFF
PCF_SPECIALCHARS 支持特殊字符
PCF_TOTALTIMEOUTS 支持总(占用时间)超时
PCF_XONXOFF 支持XON/XOFF流控制
标准RS-232和WINDOW支持除PCF_16BITMODE和PCF_SPECIALCHAR外的所有功能

dwSettableParams
SP_BAUD 可配置波特率
SP_DATABITS 可配置数据位个数
SP_HANDSHAKING 可配置握手(流控制)
SP_PARITY 可配置奇偶校验模式
SP_PARITY_CHECK 可配置奇偶校验允许/禁止
SP_RLSD 可配置RLSD(接收信号检测)
SP_STOPBITS 可配置停止位个数
标准RS-232和WINDOW支持以上所有功能

wSettableData
DATABITS_5 5个数据位
DATABITS_6 6个数据位
DATABITS_7 7个数据位
DATABITS_8 8个数据位
DATABITS_16 16个数据位
DATABITS_16X 通过串行硬件线路的特殊宽度路径
WINDOWS 95支持16的所有设置

5.DCB结构:
typedef struct _DCB {// dcb
DWORD DCBlength; // sizeof(DCB)
DWORD BaudRate; // current baud rate
指定当前的波特率
DWORD fBinary: 1; // binary mode, no EOF check
指定是否允许二进制模式,
WINDOWS 95中必须为TRUE
DWORD fParity: 1; // enable parity checking
指定奇偶校验是否允许
DWORD fOutxCtsFlow:1; // CTS output flow control
指定CTS是否用于检测发送控制。
当为TRUE是CTS为OFF,发送将被挂起。
DWORD fOutxDsrFlow:1; // DSR output flow control
指定CTS是否用于检测发送控制。
当为TRUE是CTS为OFF,发送将被挂起。
DWORD fDtrControl:2; // DTR flow control type
DTR_CONTROL_DISABLE值将DTR置为OFF,
DTR_CONTROL_ENABLE值将DTR置为ON,
DTR_CONTROL_HANDSHAKE允许DTR"握手"
DWORD fDsrSensitivity:1; // DSR sensitivity
当该值为TRUE时DSR为OFF时接收的字节被忽略
DWORD fTXContinueOnXoff:1; // XOFF continues Tx
指定当接收缓冲区已满,并且驱动程序已经发
送出XoffChar字符时发送是否停止。
TRUE时,在接收缓冲区接收到缓冲区已满的字
节XoffLim且驱动程序已经发送出XoffChar字符中
止接收字节之后,发送继续进行。
FALSE时,在接收缓冲区接收到代表缓冲区已空
的字节XonChar且驱动程序已经发送出恢复发送
的XonChar之后,发送继续进行。
DWORD fOutX: 1; // XON/XOFF out flow control
TRUE时,接收到XoffChar之后便停止发送
接收到XonChar之后将重新开始
DWORD fInX: 1; // XON/XOFF in flow control
TRUE时,接收缓冲区接收到代表缓冲区满的
XoffLim之后,XoffChar发送出去
接收缓冲区接收到代表缓冲区空的
XonLim之后,XonChar发送出

DWORD fErrorChar: 1; // enable error replacement
该值为TRUE且fParity为TRUE时,用ErrorChar
成员指定的字符代替奇偶校验错误的接收字

DWORD fNull: 1; // enable null stripping
TRUE时,接收时去掉空(0值)字节
DWORD fRtsControl:2; // RTS flow control
RTS_CONTROL_DISABLE时,RTS置为OFF
RTS_CONTROL_ENABLE时, RTS置为ON
RTS_CONTROL_HANDSHAKE时,
当接收缓冲区小于半满时RTS为ON
当接收缓冲区超过四分之三满时RTS为OFF
RTS_CONTROL_TOGGLE时,
当接收缓冲区仍有剩余字节时RTS为ON
否则缺省为OFF
DWORD fAbortOnError:1; // abort reads/writes on error
TRUE时,有错误发生时中止读和写操作
DWORD fDummy2:17; // reserved
未使用
WORD wReserved; // not currently used
未使用,必须为0
WORD XonLim; // transmit XON threshold
指定在XON字符发送这前接收缓冲区中可允许
的最小字节数
WORD XoffLim; // transmit XOFF threshold
指定在XOFF字符发送这前接收缓冲区中可允许
的最小字节数
BYTE ByteSize; // number of bits/byte, 4-8
指定端口当前使用的数据位
BYTE Parity; // 0-4=no,odd,even,mark,space
指定端口当前使用的奇偶校验方法,可能为:
EVENPARITY,MARKPARITY,NOPARITY,ODDPARITY
BYTE StopBits; // 0,1,2 = 1, 1.5, 2
指定端口当前使用的停止位数,可能为:
ONESTOPBIT,ONE5STOPBITS,TWOSTOPBITS
char XonChar; // Tx and Rx XON character
指定用于发送和接收字符XON的值
char XoffChar; // Tx and Rx XOFF character
指定用于发送和接收字符XOFF值
char ErrorChar; // error replacement character
本字符用来代替接收到的奇偶校验发生错误时
的值
char EofChar; // end of input character
当没有使用二进制模式时,本字符可用来指示
数据的结束
char EvtChar; // received event character
当接收到此字符时,会产生一个事件
WORD wReserved1; // reserved; do not use
未使用
} DCB;


6.改变端口设置
使用如下的两个方法
BOOL GetCommState(hComm,&dcb);
BOOL SetCommState(hComm,&dcb);

7,改变普通设置
BuildCommDCB(szSettings,&DCB);
szSettings的格式:baud parity data stop
例: "baud=96 parity=n data=8 stop=1"
简写:"96,N,8,1"
szSettings 的有效值
baud:
11 or 110 = 110 bps
15 or 150 = 150 bps
30 or 300 = 300 bps
60 or 600 = 600 bps
12 or 1200 = 1200 bps
24 or 2400 = 2400 bps
48 or 4800 = 4800 bps
96 or 9600 = 9600 bps
19 or 19200= 19200bps
parity:
n=none
e=even
o=odd
m=mark
s=space
data:
5,6,7,8
StopBit
1,1.5,2

8.COMMCONFIG结构:
typedef struct _COMM_CONFIG {
DWORD dwSize;
WORD wVersion;
WORD wReserved;
DCB dcb;
DWORD dwProviderSubType;
DWORD dwProviderOffset;
DWORD dwProviderSize;
WCHAR wcProviderData[1];
} COMMCONFIG, *LPCOMMCONFIG;
可方便的使用BOOL CommConfigDialog(
LPTSTR lpszName,
HWND hWnd,
LPCOMMCONFIG lpCC);
来设置串行口。

9.超时设置:
可通过COMMTIMEOUTS结构设置超时,
typedef struct _COMMTIMEOUTS {
DWORD ReadIntervalTimeout;
DWORD ReadTotalTimeoutMultiplier;
DWORD ReadTotalTimeoutConstant;
DWORD WriteTotalTimeoutMultiplier;
DWORD WriteTotalTimeoutConstant;
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;
区间超时:(仅对从端口中读取数据有用)它指定在读取两个字符之间要经历的时间
总超时: 当读或写特定的字节数需要的总时间超过某一阈值时,超时触发.
超时公式:
ReadTotalTimeout = (ReadTotalTimeoutMultiplier * bytes_to_read)
+ ReadToTaltimeoutConstant
WriteTotalTimeout = (WriteTotalTimeoutMuliplier * bytes_to_write)
+ WritetoTotalTimeoutConstant
NOTE:在设置超时时参数0为无限等待,既无超时
参数MAXDWORD为立即返回
超时设置:
GetCommTimeouts(hComm,&timeouts);
SetCommTimeouts(hComm,&timeouts);

10.查询方式读写数据
例程:
COMMTIMEOUTS to;
DWORD ReadThread(LPDWORD lpdwParam)
{
BYTE inbuff[100];
DWORD nBytesRead;
if(!(cp.dwProvCapabilities&PCF_INTTIMEOUTS))
return 1L;
memset(&to,0,sizeof(to));
to.ReadIntervalTimeout = MAXDWORD;
SetCommTimeouts(hComm,&to);
while(bReading)
{
if(!ReadFile(hComm,inbuff,100,&nBytesRead,NULL))
locProcessCommError(GetLastError());
else
if(nBytesRead)
locProcessBytes(inbuff,nBytesRead);
}
PurgeComm(hComm,PURGE_RXCLEAR);
return 0L;
}

NOTE:
PurgeComm()是一个清除函数,它可以中止任何未决的后台读或写,并且
可以冲掉I/O缓冲区.
BOOL PurgeComm(HANDLE hFile,DWORD dwFlags);
dwFlages的有效值:
PURGE_TXABORT: 中止后台写操作
PRUGE_RXABORT: 中止后台读操作
PRUGE_TXCLEAR: 清除发送缓冲区
PRUGE_RXCLEAR: 清除接收缓冲区
技巧:
可通过ClearCommError()来确定接收缓区中处于等待的字节数。
BOOL ClearCommError(
HANDLE hFile, // handle to communications device
LPDWORD lpErrors, // pointer to variable to receive error codes
LPCOMSTAT lpStat // pointer to buffer for communications status
);
ClearCommError()将返回一个COMSTAT结构:
typedef struct _COMSTAT { // cst
DWORD fCtsHold : 1; // Tx waiting for CTS signal
DWORD fDsrHold : 1; // Tx waiting for DSR signal
DWORD fRlsdHold : 1; // Tx waiting for RLSD signal
DWORD fXoffHold : 1; // Tx waiting, XOFF char rec`d
DWORD fXoffSent : 1; // Tx waiting, XOFF char sent
DWORD fEof : 1; // EOF character sent
DWORD fTxim : 1; // character waiting for Tx
DWORD fReserved : 25; // reserved
DWORD cbInQue; // bytes in input buffer
DWORD cbOutQue; // bytes in output buffer
} COMSTAT, *LPCOMSTAT;
其中的cbInQue和cbOutQue中即为缓冲区字节。

11.同步I/O读写数据
COMMTIOMOUTS to;
DWORD ReadThread(LPDWORD lpdwParam)
{
BYTE inbuff[100];
DWORD nByteRead,dwErrorMask,nToRead;
COMSTAT comstat;
if(!cp.dwProvCapabilities&PCF_TOTALTIMEOUTS)
return 1L;
memset(&to,0,sizeof(to));
to.ReadTotalTimeoutMultiplier = 5;
to.ReadTotalTimeoutConstant = 50;
SetCommTimeouts(hComm,&to);
while(bReading)
{
ClearCommError(hComm,&dwErrorMask,&comstat);
if(dwErrorMask)
locProcessCommError(dwErrorMask);
if(comstat.cbInQue >100)
nToRead = 100;
else
nToRead = comstat.cbInQue;
if(nToRead == 0)
continue;
if(!ReadFile(hComm,inbuff,nToRead,&nBytesRead,NULL))
locProcessCommError(GetLastError());
else
if(nBytesRead)
locProcessBytes(inbuff,nBytesRead);
}
return 0L;
}

12.异步I/O读写数据
当CreateFile()中的fdwAttrsAndFlags参数为FILE_FLAG_OVERLAPPEN时,
端口是为异步I/O打开的,此时可以在ReadFile的最后一个参数中指定一个
OVERLAPPED结构,使数据的读操作在后台进行。WINDOWS 95包括了异步
I/O的许多变种。
typedef struct _OVERLAPPED {
DWORD Internal;
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
HANDLE hEvent;
} OVERLAPPED;
对于串行口仅hEvent成员有效,其于成员必须为0。
例程:
COMMTIMEOUTS to;
...
DWORD ReadThread((LPDWORD lpdwParam)
{
BYTE inbuff[100];
DWORD nRytesRead,endtime,lrc;
static OVERLAPPED o;
if(!cp.dwProvCapabilities & PCF_TOTALTIMEOUTS)
return 1L;
memset(&to,0,sizeof(to));
to.ReadTotalTimeoutMultiplier = 5;
to.ReadTotalTimeoutConstant = 1000;
SetCommTimeouts(hComm,&to);
o.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
while(bReading)
{
if(!ReadFile(hComm,inbuff,10,&nBytesRead,&o))
{
nBytesRead = 0;
if(lrc=GetLastError() == ERROR_IO_PENDING)
{
endtime = GetTickCount() + 1000;
while(!GetOverlappedResult(hComm,&o,&nBytesRead,FALSE))
if(GetTickCount() > endtime) break;
}
if(nBytesRead) locProcessBytes(inbuff,nBytesRead);
}
else
{
if(nBytesRead) locProcessBytes(inbuff,nBytesRead);
ResetEvent(o.hEvent);
}
}
PurgeComm(hComm,PURGE_RXCLEAR);
return 0L;
}

这一例程是对一开始读缓冲区就读到所需的字节时的处理:
while(bReading)
{
if(!ReadFile(hComm,inbuff,10,&nBytesRead,&o))
{
if((lrc=GetLastError()) ==ERROR_IO_PENDING)
{
if(GetOverlappedResult(hComm,&o,&nBytesRead,TRUE))
{
if(nBytesRead)
locProcessBytesa(inbuff,nBytesRead);
}
else
locProcessCommError(GetLastError());
}
else
locProcessCommError(GetLastError));
}
else
if(nBytesRead) locProcessBytes(inbuff,nBytesRead);
ResetEvent(o.hEvent);
}

13.事件驱I/O读写:
GetCommMask(hComm,&dwMask)
Windows 95报告给应用程序的事件由此方法返回。
SetCommMasl(hComm,&dwMask)
添加或修改Windows 95所报告的事件列表。
事件掩码如下:
EV_BREAK 检测到输入为止
EV_CTS CTS(清除发送)信号改变状态
EV_DSR DSR(数据设置就绪)信号改变状态
EV_ERR 发生了线路状态错误.
线路状态错误为:
CE_FRAME(帧错误)
CE_OVERRUN(接收缓冲区超限)
CE_RXPARITY(奇偶校验错误)
EV_RING 检测到振铃
EV_RLSD RLSD(接收线路信号检测)信号改变状态
EV_EXCHAR 接收到一个字符,并放入输入缓冲区
EV_RXFLAG 接收到事件字符(DCB成员的EvtChar成员),度放入输入缓冲区
EV_TXEMPTY 输出缓冲区中最后一个字符发送出去
在用SetCommMask指定了有用的事件后,应用程序可调用WaitCommEvent()来等
待事件发生.
BOOL WaitCommEvent(
HANDLE hFile, // handle of communications device
LPDWORD lpEvtMask, // address of variable for event that occurred
LPOVERLAPPED lpOverlapped, // address of overlapped structure
);
此方法可以以同步或异步方式操作
例程:
COMMTIMEOUTS to;
...
DWORD ReadTherad(LPDWORD lpdwParam)
{
BYTE binbuff[100];
DWORD nBytesRead,dwEvent,dwError;
COMSTAT cs;
SetCommMask(hComm,EV_RXHAR);
while(bReading)
{
if(WaitCommEvent(hComm,&dwEvent,NULL))
{
ClearCommError(hComm,&dwError,&cs);
if((dwEvent&EV_RXCHAR)&&cs.cbInQue)
{
if(!ReadFile(hComm,inbuff,cs.cbInQue,&nBytesRead,NULL)
locProcessCommError(GetLastError());
}
else
{
if(nByteRead)
locProcessBytes(inbuff,nBytesRead);
}
else
locProcessCommError(GetLastError());
}
PurgeComm(hComm,PURGE_RXCLEAR);
return 0L;
}
NOTE: SetCommMask(hComm,0)可使WaitCommEvent()中止.

可使用GetCommmodemStatus()方法,例程:
if(cp.dwProvCapabilities&PCF_RTSCTS)
{
SetCommMask(hComm,EV_CTS);
WaitCommEvent(hComm,&dwMask,NULL);
if(dwMask&EV_CTS)
{
GetCommModemStatus(hComm,&dwStatus)
if(dwStatus&MS_CTS_ON) /* CTS stransition OFF-ON */
else /* CTS stransition ON-OFF */
}
}
MS_CTS_ON CTS为ON
MS_DSR_ON DSR为ON
MS_RING_ON RING为ON
MS_ELSD_ON RLSD为ON

14.错误
当发生错误时应用方法ClearCommError(hComm,&dwErrorMask,&constat)
得到错误掩码。
CE_BREAK 中止条件
CE_FRAME 帧错误
CW_IOE 一般I/O错误,常伴有更为详细的错误标志
CE_MODE 不支持请求的模式
CE_OVERRUN 缓冲区超限下一个字符将丢失
CE_RXOVER 接收缓冲区超限
CE_RXPARITY 奇偶校验错误
CE_TXFULL 发送缓冲区满
CE_DNS 没有选择并行设备
CE_PTO 并行设备发生超时
CE_OOP 并行设备缺纸

15.控制命令
EscapeCommFunction()可将硬件信号置ON或OFF,模拟XON或XOFF
BOOL EscapeCommFunction(
HANDLE hFile, // handle to communications device
DWORD dwFunc // extended function to perform
);
dwFunc的有效值(可用‘|’同时使用多个值)
CLRDTR DTR置OFF
CLRRTS RTS置OFF
SETDTR STR置ON
SETRTS TRS置ON
SETXOFF 模拟XOFF字符的接收
SETXON 模拟XON字符的接收
SETBREAK 在发送中产生一个中止
CLRBREAK 在发送中清除中止 

C++学习要点:


1. 传指针时,我们可以通过指针来修改它在外部所指向的内容。但如果要修改外部指针所指向的对象是不可能的。例如传递外部指针到函数内来分配空间,必须传递指针的指针或指针的引用。

2. char carry[10] = {0}; 编译器会将其后所有的东西都置0;

3. 函数返回值为const时,返回的东西付给一个类型相同的标示后其不能为左值;

4. const int *i; int const *i; int * const i; 前两个功能相同,说明I所指向的内容不变;最后一个说明指针指向的地址不变,但内容可变。

5. 类中的const成员函数。定义为在原型后加const。常量函数不能修改类中的任何属性。但有两种方法可以修改。

a) {(myclass *)this->member1 = values;}

b) 将一个成员定义成mutable即可被常量函数修改。

6. 类中的常量const 类型的,不能在类中被用来定义数组。而enum {ONE=100; TWO=2};定义的ONE、TWO却可以。通常的enum定义的置分配问题:enum A{ L=9, Z};此时Z的值为10。

7. 用const定义的int可用来开辟数组,但const定义的常量数组中的元素,不能用来定义数组。

8. 用sizeof计算变量的空间,如果是数组,按实际空间返回;常量字符串(实际上是在静态内存区开辟的变量)sizeof返回比实际长度加一。如果是指针则不考虑它指向的空间大小,仅仅返回指针类型的大小。如果用sizeof计算函数的行参,即使是属组也仅仅返回一个相关类型指针的大小。

9. 形如int iarray[] = {12, 124, 433};编译器会自动给iarray分配3个元素的长度。元素长度的个数计算公式为sizeof(iarray) / sizeof(*iarray)。

10. 拷贝构造函数:当行参和实参结合时,如果是复杂对象的传值类型,则调用拷贝构造函数生成一个临时对象作为实参,退出函数时,临时对象被调用析构函数释放。当返回值是复杂对象是,也是调用拷贝构造函数来赋值。这就出现构造函数和析构函数被调用次数不相等的情况。拷贝构造函数的原型为A(A&),我们可在类中重载。(缺省的拷贝构造函数是使用位(bit)拷贝方法:浅层拷贝,不拷贝指针指向的内容)。

11. volatile类型的变量告诉编译器,本变量不需要进行代码优化。在多线程的应用中,我们如果读入一个变量到寄存器,此时时间片到期,去处理其他线程了,在重新获得处理机时,volatile类型告诉处理机,重新从变量读取数据到寄存器,而不是用寄存器数据直接处理,这样可以防止脏数据。

12. class 和struct在一定程度上有相同的功能,只不过前者缺省的成员是私有的,后者在缺省时成员为共有的。故而class不是c++必需的保留字

13. c和c++编译器,对相同的函数名编译后生成的相同的标示不同,故而在引用c的库文件时必须使用extern “C”告诉编译器,它是c的函数,按c的规则编译。通常我们使用的标准头文件已被处理过。

14. #include “filename”; #include <filename>,前者先在当前目录下寻找文件,如果找不到再到系统规定的路径下找,后者直接到系统规定的路径下找。

15. 任何地方分配的静态变量(static),其生命周期和主进程相同。第二次定义一个已存在的static变量,对变量的内用无影响,但它的可见范围只在定义的范围内。(考研曾作错!)(从静态变量的特性不难理解,类中的static类型是所有对象共享的)

16. 内联函数(inline)在实现上实际和宏类似,在内联函数出现的地方将函数展开来避免函数调用时的出栈、如栈,提高效率。但内联函数的代价是:代码增大。inline函数适合成员函数和自由函数。在类中实现的函数自动为内联函数。inline必须定义到函数的实现上,例如:inline int PlusOne(int) 是无效的。友元函数在类的体内被实现自动变为内联函数。

17. #include <iostream.h>

#define DEBUG(X) cout<<#X"="<<X<<endl

其中的#X表示X被当作字符串输出。

18. assert(0 != 0); 如果assert中的条件为假,则运行期间回退出程序,且报告出错代码的行号。(#include <assert.h>)

19. 静态对象在main结束或exit()被调用时才调用自身的析构函数。这意味着,在对象的析构函数中调用exit()是很危险的,有可能进入一个死循环中。调用abort()来退出函数,静态对象的析构函数并不会被调用。我们可以用atexit()来指定跳出main或调用exit时要执行的操作,用atexit注册的函数,可以在所有对象的析构函数之前调用。

void exit_fn2(void)

{

printf("Exit function #2 called\n");

} //处理函数

atexit(exit_fn2);

20. 全局变量实际上用的是静态存储。静态变量的构造是在进入main之前调用的,在main结束时调用它的析构函数。变量的名字由小范围(c++而言):

//*.cpp

int a; //静态变量,但为 extern int a; 即它是全局的,外部可见的

static int b; //静态变量,static 和extern相反,只在*.cpp中有效,对其他单元(文件)是不可见的。函数的定义和上面相同。

main()

{ }

类的静态成员变量可以如下赋值:int X::s=23;(在*.cpp中,无论公私都可以)

21. 名字空间(namespace): 定义一个名字空间,然后使用unsing就可以将当前的类型上下文转换名字空间所定地的.

namespace math

{

enum sign{positive, negative};

class integer{

int i;

sign s;

public:

interger(int I=0): i(i) {………}

sign Sign() {………}

…………………..

};//end class

interger A, B, C;

interger divide(interger, interger);

}//no ;

 

void q()

{

using namespace math;

interger A; //hides math::A

A.Sign(negative);

Math::A.Sign(positive);

}

22. 一般对于函数flaot f(int a, int b); 某些c++编译器编译后生成_f_int_int的名字,有些c编译器则生成_f的名字。故在c++中链接c的库函数时要用extern “C”告诉编译器,按c的规则来编译函数。类似的还有extern “C”{#include “myhead.h”},c++还支持extern “C++”{}.

23. 在函数调用时,传引用也是将指针压栈。

24. 构造函数、析构函数、赋值构造函数、重载的=,四者的调用顺序:(三种函数都已实现)

a) X x; X a=x;

result:

X:construct

X:copy_struct

b) X x; X a; a=x;

Result:

X:construct

X:construct

X:copy_stru

operator =

X:destruct

如果没有赋值构造函数则结果:

X:construct

X:construcC和C++的区别有什么

今天在网易上看到有人问C和C++的区别有什么,在这里简略说点.
  其他的东西都不需要多说,就象类,继承,引用等,大家都知道.
  这里讲的是调用编译的区别.大家看WIN32 SDK的头文件,总是可以看到

    
ifdef __cplusplus
    extern "C"
        
endif

        
ifdef __cplusplus
        
    
endif

  这个就是直接能够体现实际编程时区别的地方. 在WIN系列下.所有的WIN32 SDK提供的LIB都是以C的形式存在的.当然,C和C++同样都支持C,STDCALL,FASTCALL调用.为什么系统提供C编译器编译的LIB而不是C++编译的LIB呢?这里其实就是C和C++编译器不同的地方.

  所有的函数名称只有在汇编编译器下才最清楚.因为经汇编编译器编译的函数不经过任何修饰.
C的编译器编译出来的函数名称如果在汇编编译器看来一个C调用将在函数名前家下划线('_').而一个STDCALL的函数将是_FUNC@NUMBER的形式.如FUNC(void)经过编译器后成为_FUNC@0.一个FASTCALL调用的函数被编译成@FUNC@0.顺便提一下.在WIN32的编译器里不再需要PASCALL调用.VC6已经取消了对PASCALL的支持.
光看C的编译还不够,看一下C++编译器是怎么干的.在缺省情况下.一个C++的函数经过C++编译器后编译出的函数名包括函数名,所属的类,参数类型,调用约定,返回类型.而且更要命的是这么多的信息,只有函数名和类名在编译后还依稀可见.其他就是一长串的ABCD字母,根本就是无法辨认其意义的.我们在VC手册里可以看到

一个例子:

void __stdcall b::c(float); -----------> ?c@b@@QAGXM@Z
  一个函数被编译得连名字也不知道怎么样了.这么一来.如果SDK提供的是C++编译器提供了LIB.那么可以说就无法编译任何一个完整的WIN程序.更加不用说什么混合语言编程.

  现在,VC编译器提供了个extern语句.当出现extern 'C'语句,括号里的函数将以C方式经过编译器.从而使提供库程序方便那么点.


C++指针使用方法解惑

在下列函数声明中,为什么要同时使用*和&符号?以及什么场合使用这种声明方式?
void func1( MYCLASS *&pBuildingElement );
论坛中经常有人问到这样的问题。本文试图通过一些实际的指针使用经验来解释这个问题。
仔细看一下这种声明方式,确实有点让人迷惑。在某种意义上,"*"和"&"是意思相对的两个东西,把它们放在一起有什么意义呢?。为了理解指针的这种做法,我们先复习一下C/C++编程中无所不在的指针概念。我们都知道MYCLASS*的意思:指向某个对象的指针,此对象的类型为MYCLASS。
void func1(MYCLASS *pMyClass);

// 例如:
MYCLASS* p = new MYCLASS;
func1(p);
上面这段代码的这种处理方法想必谁都用过,创建一个MYCLASS对象,然后将它传入func1函数。现在假设此函数要修改pMyClass:
void func1(MYCLASS *pMyClass)
{
DoSomething(pMyClass);
pMyClass = // 其它对象的指针
}

第二条语句在函数过程中只修改了pMyClass的值。并没有修改调用者的变量p的值。如果p指向某个位于地址0x008a00的对象,当func1返回时,它仍然指向这个特定的对象。(除非func1有bug将堆弄乱了,完全有这种可能。)
现在假设你想要在func1中修改p的值。这是你的权利。调用者传入一个指针,然后函数给这个指针赋值。以往一般都是传双指针,即指针的指针,例如,CMyClass**。
MYCLASS* p = NULL;
func1(&p);

void func1(MYCLASS** pMyClass);
{
*pMyClass = new MYCLASS;
……
}

调用func1之后,p指向新的对象。在COM编程中,你到处都会碰到这样的用法--例如在查询对象接口的QueryInterface函数中:
interface ISomeInterface {
HRESULT QueryInterface(IID &iid, void** ppvObj);
……
};
LPSOMEINTERFACE p=NULL;
pOb->QueryInterface(IID_SOMEINTERFACE, &p);

此处,p是SOMEINTERFACE类型的指针,所以&p便是指针的指针,在QueryInterface返回的时候,如果调用成功,则变量p包含一个指向新的接口的指针。
如果你理解指针的指针,那么你肯定就理解指针引用,因为它们完全是一回事。如果你象下面这样声明函数:

void func1(MYCLASS *&pMyClass);
{
pMyClass = new MYCLASS;
……
}

其实,它和前面所讲得指针的指针例子是一码事,只是语法有所不同。传递的时候不用传p的地址&p,而是直接传p本身:

MYCLASS* p = NULL;
func1(p);

在调用之后,p指向一个新的对象。一般来讲,引用的原理或多或少就象一个指针,从语法上看它就是一个普通变量。所以只要你碰到*&,就应该想到**。也就是说这个函数修改或可能修改调用者的指针,而调用者象普通变量一样传递这个指针,不使用地址操作符&。
至于说什么场合要使用这种方法,我会说,极少。MFC在其集合类中用到了它--例如,CObList,它是一个CObjects指针列表。
class CObList : public CObject {
……

// 获取/修改指定位置的元素
CObject*& GetAt(POSITION position);
CObject* GetAt(POSITION position) const;
};

这里有两个GetAt函数,功能都是获取给定位置的元素。区别何在呢?
区别在于一个让你修改列表中的对象,另一个则不行。所以如果你写成下面这样:
CObject* pObj = mylist.GetAt(pos);

则pObj是列表中某个对象的指针,如果接着改变pObj的值:
pObj = pSomeOtherObj;

这并改变不了在位置pos处的对象地址,而仅仅是改变了变量pObj。但是,如果你写成下面这样:
CObject*& rpObj = mylist.GetAt(pos);

现在,rpObj是引用一个列表中的对象的指针,所以当改变rpObj时,也会改变列表中位置pos处的对象地址--换句话说,替代了这个对象。这就是为什么CObList会有两个GetAt函数的缘故。一个可以修改指针的值,另一个则不能。注意我在此说的是指针,不是对象本身。这两个函数都可以修改对象,但只有*&版本可以替代对象。
在C/C++中引用是很重要的,同时也是高效的处理手段。所以要想成为C/C++高手,对引用的概念没有透彻的理解和熟练的应用是不行的。

1.线程:在stdafx.h中包含<afxmt.h>
不要在头文件中进行函数实现,放在app中

2.调用主对话框或主窗体的大小:
AfxGetMainWnd()->GetWindowRect(&largerect);

3.改变背景颜色:
如果你的工程是基于对话框的,可以添加消息WM_CTLCOLOR
响应的处理函数:

HBRUSH CFPR_TimeCheckDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
 HBRUSH  m_hRedBrush  =    CreateSolidBrush(RGB(...,..,...));
 HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
 
 // TODO: Change any attributes of the DC here
 if(nCtlColor==CTLCOLOR_DLG){
  pDC->SetBkColor(RGB(20,123,56));
  hbr=m_hRedBrush;
  return hbr;
 } 
 else{
  return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
 }
 // TODO: Return a different brush if the default is not desired
 
}

4.全屏(最大化):
ShowWindow(hwndDlg, SW_SHOWMAXIMIZED);

5.获得屏幕大小:
获取屏幕大小:单位(象素)GetSystemMetrics;
获取窗口大小:GetWindowRect
屏幕宽=GetSystemMetrics(SM_CXSCREEN);
屏幕高=GetSystemMetrics(SM_CYSCREEN);
在这个对话框类里面,直接用GetWindowRect(&largerect);就可以了呀。
注:以像素为单位

6.CDC的赋值:
定义了CDC* pDc,但没有看到你给pDc赋值阿,空指针怎能不错?如果是在OnDraw(CDC*)中,去掉这多余的定义;如果没有现成的pDc,想办法得到,如
pDc=GetDC();
pDc=GetClientDC();
等等。用完后记得释放阿:ReleaseDC(pDc)

7.移动窗口位置
MoveWindow(x,y,宽,高,TRUE);
8.在CMyApp.cpp 文件中#endif 之后加入某函数则程序一执行就调用
  在return FALSE之前加入关闭函数,则程序正常执行结束便调用关闭函数,例如:

#ifdef _AFXDLL
 Enable3dControls();   // Call this when using MFC in a shared DLL
#else
 Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif

 g_gasbox.OpenPort(1, 19200);
 g_dyno.OpenPort(2, 9600);

 CProjectDlg dlg;
 m_pMainWnd = &dlg;
 int nResponse = dlg.DoModal();
 if (nResponse == IDOK)
 {
  // TODO: Place code here to handle when the dialog is
  //  dismissed with OK
 }
 else if (nResponse == IDCANCEL)
 {
  // TODO: Place code here to handle when the dialog is
  //  dismissed with Cancel
 }

 g_gasbox.ClosePort();
 g_dyno.ClosePort();

 // Since the dialog has been closed, return FALSE so that we exit the
 //  application, rather than start the application's message pump.
 return FALSE;
}

9.包含模板类<afxtempl.h>

10.设置窗体样式(下例全屏并且没有CAPTION);
LONG style1=::GetWindowLong(m_hWnd,GWL_STYLE);
 style1&=~WS_CAPTION;
 ::SetWindowLong(m_hWnd,GWL_STYLE,style1);
 int screenx=GetSystemMetrics(SM_CXSCREEN);
 int screeny=GetSystemMetrics(SM_CYSCREEN);
 // resize:
 SetWindowPos(NULL,0,0,screenx,screeny,SWP_NOZORDER);

11.让静态文本框改变背景
继承CStatic 类,重载 CtlColor
HBRUSH CMyStatic::CtlColor(CDC* pDC, UINT nCtlColor)
{
 // TODO: Change any attributes of the DC here
 
 // TODO: Return a non-NULL brush if the parent's handler should not be called
// return NULL;
 ASSERT(nCtlColor == CTLCOLOR_STATIC);

 pDC->SetBkMode( TRANSPARENT );

 return (HBRUSH)GetStockObject( NULL_BRUSH );

}

12.在两个对话框的控件上传值

在CDialog2中定义一个static的变量m_judge
假设IDC_TEXT对应的变量是m_text则:
if(CDialog1.DoModul()==IDOK)
{
  CDialog2::m_judge=m_text;//就可以了
}


刚才有大侠说了很多经验,佩服记录之余,补充一点:
取得可执行文件目录最简单的办法的:
CString path=::__argv[0];
path=path.Left(path.ReverseFind('\\')+1);
 

operator =

X:destruct

(如果直接X a=x;这不掉用一般的构造函数,调用复制构造函数)

指向类的成员函数的指针:设 int X:: a(void){}

X x;

int (X:: *pf)(void)= &X::a;

(x.*pf)();

指向成员变量的指针: 设int i; 是X的成员变量

int X::*pm = &X::i;

X x;

默认分类 | 阅读 6631 次
文章评论,共0条
游客请输入验证码
浏览44545次
文章分类