我以前写线程时要么老老实实照着声明写,要么使用C++类的静态成员函数来作为回调函数,经常会因为线程代码而破坏封装.之前虽然知道类成员函数的展开形式,但从没想过利用过它,昨天看深入ATL时无意中学会了这一招:)
类成员方法是一个比较特殊的函数,它在编译时会被转化成普通函数,比如有TMyClass类:
class TMyClass{
void Func();
};
这个TMyClass::Func最终会转化成 void Func(TMyClass *this); 也就是说在原第一个参数前插入指向对象本身的this指针。
我们可以利用这个特性写一个非静态类成员方法来直接作为线程回调函数,先看_beginthread函数的定义:
unsigned long _RTLENTRY _EXPFUNC _beginthread (void (_USERENTRY *__start)(void *),unsigned __stksize, void *__arg);
其中的第一个参数就是作为线程执行主体的回调函数。它的原型是:void Func(void *),这个void*参数是作为自定义数据传入的。对比一下上面所说的TMyClass::Func的最终形式,它正好可以符合这里的要求。
现在做个实验:
#include <stdio.h>
#include <process.h>
class TMyClass{
int m_nCount;
int m_nId;
public:
TMyClass(int nId,int nCount)
:m_nId(nId),m_nCount(nCount)
{
}
void _USERENTRY ThreadProc() // 类成员方法
{
for(int i=0; i<m_nCount; i++) // 根据m_nCount成员打印一排数字
{
printf("Class%d : %d\n",m_nId,i);
}
}
};
int main(int argc, char* argv[])
{
union { // 联合类,用于转换类成员方法指针到普通函数指针(试过编译器不允许在这两种函数之间强制转换),不知道有没有更好的方法。
void (_USERENTRY *ThreadProc)(void *);
void (_USERENTRY TMyClass::*MemberProc)();
} Proc; // 尽管联合里的两种函数类型现在看起来有很大不同,但它们的最终形式是相同的。
TMyClass MyClass1(1,10),MyClass2(2,5); // 产生两个TMyClass对象
Proc.MemberProc = &TMyClass::ThreadProc; // 转换,Proc.ThreadProc就是对应的普通函数指针了
_beginthread(Proc.ThreadProc,4096,&MyClass1); // 开始线程,这里的Proc.ThreadProc实际上是TMyClass::ThreadProc, 它要的this指针是我们给的&MyClass1。
_beginthread(Proc.ThreadProc,4096,&MyClass2);
system("pause");
return 0;
}
运行!神奇吧?:-)
其实不止线程回调函数,其实只要是形如Func(void*,...)的回调函数都可以用这种方法直接使用类成员方法。(前提是第一个void*是自定义数据,也就是说它不能有其它功能)。
转自:http://blog.csdn.net/waiting4you/archive/2007/12/29/2000796.aspx
posted @
2008-07-22 03:13 幽幽 阅读(3219) |
评论 (1) |
编辑 收藏
滚动控件(ScrollBar)
滚动条(ScrollBar)主要用来从某一预定义值范围内快速有效地进行选择。滚动条分垂直滚动条和水平滚动条两种。在滚动条内有一个滚动框,用来表示当前的值。用鼠标单击滚动条,可以使滚动框移动一页,鼠标单击滚动条两端的剪头可以使滚动框移动一行,也可以直接拖动滚动框。许多窗口控件如列表框和组合框等都带有滚动条子窗口。Win32的滚动条支持比例滚动框,即用滚动框的大小来反映页相对于整个范围的大小。
当CreateWindowEx创建滚动条时,其风格常数中带SBS_VERT为水平滚动条,不带SBS_VERT或带SBS_HORZ为垂直滚动条。
创建控件时应初始化滚动条的各种参数。
应用程序可以通过调用SendMessage向控件发送如下消息来设定控件各种参数。
uMsg |
wParam |
lParam |
说明 |
SBM_ENABLE_ARROWS |
ESB_DISABLE_BOTH |
0 |
禁止双向滚动剪头 |
ESB_DISABLE_DOWN |
0 |
禁止向下滚动剪头 |
ESB_DISABLE_LTUP |
0 |
禁止向上和向左滚动剪头 |
ESB_DISABLE_LEFT |
0 |
禁止向左滚动剪头 |
ESB_DISABLE_RTDN |
0 |
禁止向下和向右滚动剪头 |
ESB_DISABLE_UP |
0 |
禁止向上滚动剪头 |
ESB_ENABLE_BOTH |
0 |
允许双向滚动剪头(撤消各种禁止) |
SBM_SETPOS |
指定位置 |
TRUE |
设置滚动框位置,并重绘控件 |
FALSE |
设置滚动框位置,不重绘控件 |
SBM_SETRANGE |
最小值 |
最大值 |
设置滚动框位置的变化范围 |
SBM_SETRANGEREDRAW |
最小值 |
最大值 |
设置滚动框位置的变化范围,并重绘控件 |
SBM_SETSCROLLINFO |
TRUE或FALSE |
SCROLLINFO结构指针 |
本消息通过一个SCROLLINFO结构来同时指定控件的多种参数,具体指定哪些参数由结构中的fMask成员确定。wParam指定是否重绘控件,详见“SCROLLINFO结构” |
当用户在滚动条控件上进行各种操作时,其父窗口将收到WM_HSCROLL或WM_VSCROLL通知消息,同时wParam的低16位带有如下表的消息代码(nScrollCode),wParam的高16位带滚动框的指定位置(nPos),该值在消息代码等于SB_THUMBPOSITION或SB_THUMBTRACK时才有效。lParam带控件句柄(hwndScrollBar)。
应用程序可以根据消息代码做相应的操作,重新设置滚动框位置,控件本身是不会改变滚动框位置的。
消息代码 |
动作 |
响应 |
SB_LINEUP SB_LINELEFT |
用户点击了向上(左)剪头 |
滚动框位置减一,客户窗口向上(左)滚动一行。 注:这两个代码数值相等,因此可以混用,下同。 |
SB_LINEDOWN SB_LINERIGHT |
用户点击了向下(右)剪头 |
滚动框位置加一,客户窗口向下(右)滚动一行。 |
SB_PAGEUP SB_PAGELEFT |
用户点击了滚动框以上(左)剪杆 |
滚动框位置减去一个大单位,客户窗口向上(左)滚动一页。 |
SB_PAGEDOWN SB_PAGERIGHT |
用户点击了滚动框以下(右)剪杆 |
滚动框位置加上一个大单位,客户窗口向下(右)滚动一页。 |
SB_THUMBPOSITION |
用户拖动并释放滚动框到指定位置 |
设定滚动框到指定位置。客户窗口滚动到指定位置。 |
SB_THUMBTRACK |
用户正在拖动滚动框 |
设定滚动框到指定位置。客户窗口滚动到指定位置。如果应用程序需要快速浏览窗口,可以响应本消息重绘窗口,如果不需要快速浏览,可以等待收到SB_THUMBPOSITION消息时重绘窗口。 |
SB_ENDSCROLL |
用户释放按下剪头或剪杆的鼠标 |
无须做任何响应 |
应用程序可以通过调用SendMessage向控件发送如下消息来取得当前控件各种参数。
uMsg |
wParam |
lParam |
说明 |
SBM_GETPOS |
0 |
0 |
返回滚动框当前位置。 |
SBM_GETRANGE |
最小值地址指针 |
最大值地址指针 |
在指定地址中填入32位的滚动框位置的变化范围 |
SBM_GETSCROLLINFO |
0 |
SCROLLINFO结构指针 |
在一个SCROLLINFO结构中返回控件的多种参数,必须事先设定结构的fMask成员来确定具体要取得哪些参数。详见“SCROLLINFO结构” |
当控件需要重画时向每父窗口发送WM_CTLCOLORSCROLLBAR消息,同时在wParam中带控件的设备场景句柄(hDC),lParam中带控件句柄。如果应用程序响应这个消息并返回一个画刷(brush)句柄,控件将根据这个句柄绘制背景色。
SCROLLINFO结构:
SCROLLINFO STRUCT
cbSize DWORD ?
fMask DWORD ?
nMin DWORD ?
nMax DWORD ?
nPage DWORD ?
nPos DWORD ?
nTrackPos DWORD ?
SCROLLINFO ENDS
|
成员说明:
cbSize: SCROLLINFO结构长度字节数,该值在设置和查询参数时都必须填写。
fMask: 指定结构中的哪些成员是有效,该值共有如下5种选择,可以选择多种用“OR”组合起来,该值在设置和查询参数时都必须填写。
SIF_ALL :整个结构都有效
SIF_DISABLENOSCROLL:该值仅在设定参数时使用,视控件参数设定的需要来对本结构的成员进行取舍。
SIF_PAGE :nPage成员有效
SIF_POS :nPos成员有效
SIF_RANGE :nMin和nMax成员有效
nMin:滚动范围最小值
nMax:滚动范围最大值
nPage:页尺寸,用来确定比例滚动框的大小
nPos:滚动框的位置
nTrackPos:拖动时滚动框的位置,该参数只能查询,不能设置。
posted @
2008-07-21 09:57 幽幽 阅读(1706) |
评论 (3) |
编辑 收藏
滑块长度 =(int)(GetScrollInfo.nPage*(GetScrollInfo.nPage-32)/GetScrollInfo.nMax)
posted @
2008-07-13 22:23 幽幽 阅读(401) |
评论 (0) |
编辑 收藏
摘要: 为什么类(class)的成员函(member function)数不能作为回调函数(callback function)首先来看看回调函数有怎样的特点。windows中,回调函都显式(explicit)使用CALLBACK修饰符(decorator)修饰(decorated)。实际上CALLBACK就是_stdcall参数传...
阅读全文
posted @
2008-07-06 03:58 幽幽 阅读(808) |
评论 (0) |
编辑 收藏
=============================================================
GetDc函数:用于获得hWnd参数所指定窗口的客户区域的一个设备环境。
所获得的设备环境可以是通用、类或者私有类型,具体由指定窗口的类风格决定。对于通用设备环境,GetDc函数每次获取一个设备环境时都会用默认属性对它进行初始化。该函数获得的类和私有设备环境会与它们最后一次的设置保持一致。当设备环境不再需要时,应该调用ReleaseDC函数将其释放。
GetWindowDC函数:返回hWnd参数所指定的窗口的设备环境。
获得的设备环境覆盖了整个窗口(包括非客户区),例如标题栏、菜单、滚动条,以及边框。这使得程序能够在非客户区域实现自定义图形,例如自定义标题或者边框。当不再需要该设备环境时,需要调用ReleaseDC函数释放设备环境。注意,该函数只获得通用设备环境,该设备环境的任何属性改变都不会反映到窗口的私有或者类设备环境中(如果窗口有的话)
----------摘自《Delphi Win32核心API参考》
=============================================================
posted @
2008-06-26 08:27 幽幽 阅读(3053) |
评论 (0) |
编辑 收藏
void CxxxView::OnDraw(CDC* pDC)
{
::CoInitialize(NULL); // COM 初始化
HRESULT hr;
CFile file;
file.Open( "c:\\aa.jpg", CFile::modeRead | CFile::shareDenyNone ); // 读入文件内容
DWORD dwSize = file.GetLength();
HGLOBAL hMem = ::GlobalAlloc( GMEM_MOVEABLE, dwSize );
LPVOID lpBuf = ::GlobalLock( hMem );
file.ReadHuge( lpBuf, dwSize );
file.Close();
::GlobalUnlock( hMem );
IStream * pStream = NULL;
IPicture * pPicture = NULL;
// 由 HGLOBAL 得到 IStream,参数 TRUE 表示释放 IStream 的同时,释放内存
hr = ::CreateStreamOnHGlobal( hMem, TRUE, &pStream );
ASSERT ( SUCCEEDED(hr) );
hr = ::OleLoadPicture( pStream, dwSize, TRUE, IID_IPicture, ( LPVOID * )&pPicture );
ASSERT(hr==S_OK);
long nWidth,nHeight; // 宽高,MM_HIMETRIC 模式,单位是0.01毫米
pPicture->get_Width( &nWidth ); // 宽
pPicture->get_Height( &nHeight ); // 高
////////原大显示//////
CSize sz( nWidth, nHeight );
pDC->HIMETRICtoDP( &sz ); // 转换 MM_HIMETRIC 模式单位为 MM_TEXT 像素单位
pPicture->Render(pDC->m_hDC,0,0,sz.cx,sz.cy,
0,nHeight,nWidth,-nHeight,NULL);
////////按窗口尺寸显示////////
// CRect rect; GetClientRect(&rect);
// pPicture->Render(pDC->m_hDC,0,0,rect.Width(),rect.Height(),
// 0,nHeight,nWidth,-nHeight,NULL);
if ( pPicture ) pPicture->Release();// 释放 IPicture 指针
if ( pStream ) pStream->Release(); // 释放 IStream 指针,同时释放了 hMem
::CoUninitialize();
}
posted @
2008-06-24 17:15 幽幽 阅读(561) |
评论 (0) |
编辑 收藏
1 将Cstring转成TCHAR*
StrToTchar(CString temString,TCHAR * pTchar)
{
int tmpLength=0 ;
tmpLength = temString.GetLength();
TCHAR * ptemTchar = temString.GetBuffer(tmpLength);
wcscpy( pTchar,ptemTchar);
}
2 获取系统时间
CString GetSysTime()
{//得到系统时间
CString strTime;
SYSTEMTIME st;
::GetLocalTime(&st);
TCHAR datetime[20];
TCHAR times[20];
GetDateFormat(LOCALE_USER_DEFAULT,NULL,&st,_T("yyyy-MM-dd"),datetime,20);
GetTimeFormat(LOCALE_USER_DEFAULT,NULL,&st,_T("HH:mm:ss"),times,20);
strTime = (CString)datetime + _T(" ")+(CString)times;
return strTime;
}
CTime t = CTime::GetCurrentTime();
SelfInfo[8] = IntToStr(t.GetYear());
SelfInfo[9] = IntToStr(t.GetMonth());
SelfInfo[10] = IntToStr(t.GetDay());
3 写日志
void Writelog(char *str)
{
FILE *fp;
fp = fopen("\\Storage\\LogFile.txt","w+");
if(!fp)
{
return;
}
fprintf(fp,"%s\n",str);
fclose(fp);
return;
}
posted @
2008-06-23 03:59 幽幽 阅读(310) |
评论 (0) |
编辑 收藏
CListCtrl::GetItemPosition
BOOL GetItemPosition(int nItem,LPPOINT lpPoint) const
返回值:如果成功,则返回非零值,否则为0。
参数: nItem 要获取位置的项的索引值。
lpPoint 在视图坐标中接受项左上角位置POINT结构的地址,按视图坐标。
说明:获取列表视图项的位置。
//////////////////////////////////////////////////////////////
CListCtrl::GetItemRect
BOOL GetItemRect(int nItem,LPRECT lpRect,UNIT nCode) const
返回值:如果成功,则返回非零值,否则为0。
参数: nItem 要获取位置的项的索引值。
lpRect 接受绑定矩形的RECT结构的地址。
nCode 要获取绑定矩形的列表视图项的部分。它可为下列值之一: · LVIR_BOUNDS 返回整个项的绑定矩形,包括图标和标签。
· LVIR_ICON 返回图标或小图标的绑定矩形。
· LVIR_LABEL 返回项文本的绑定矩形。
说明:
在当前视图中获取某项的全部或部分的绑定矩形。
posted @
2008-06-22 10:13 幽幽 阅读(5278) |
评论 (0) |
编辑 收藏
获得CWinApp:
-在CMainFrame,CChildFrame,CDocument,CView中直接调用AfxGetApp()或用theApp
-在其它类中只能用AfxGetApp()
获得CMainFrame:
-在CMinApp中用AfxGetMainWnd()或者m_pMainWnd
-在CChildFrame中可用GetParentFrame()
-在其它类中用AfxGetMainWnd()
获得CChildFrame:
-在CView中用GetParentFrame()
-在CMainFrame中用MDIGetActive()或GetActiveFrame()
-在其它类中用AfxGetMainWnd()->MDIGetActive()或AfxGetMainWnd()->GetActiveFrame()
获得CDocument:
-在CView中用GetDocument()
-在CChildFrame中用GetActiveView()->GetDocument()
-在CMainFrame中用
-if SDI:GetActiveView()->GetDocument()
-if MDI:MDIGetActive()->GetActiveView()->GetDocument()
-在其它类中
-if SDI:AfxGetMainWnd()->GetActiveView()->GetDocument()
-if MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()->GetDocument()
获得CView:
-在CDocument中 POSITION pos = GetFirstViewPosition();GetNextView(pos)
-在CChildFrame中 GetActiveView()
-在CMainFrame中
-if SDI:GetActiveView()
-if MDI:MDIGetActive()->GetActiveView()
-在其它类中
-if SDI:AfxGetMainWnd()->GetActiveView()
-if MDI:AfxGetMainWnd()->MDIGetActive()->GetActiveView()
不过要注意在doc中要取得view的指针C*View要注意类C*View声明的问题,
因为默认情况下,mfc在*View.h中已经包含了*Doc.h,如果在*Doc.h中包含
*View.h,就会引起嵌套包含问题,这样要在*Doc.h中加入 class C*View;
而在*Doc.cpp中加入 #include "*View.h"
//////////////////////////////////////////////////////////////////
其实完全可以在CYourApp中添加各种视或文档的指针,在那些视或文档初
始化的时候将指针传给CYourApp中的对应变量,这样以后不管在哪用上面
指针只需(CYourApp*)AfxGetApp()取其属性变量即可,明了而且清楚更是
方便我一直专门操作的说:)
//////////////////////////////////////////////////////////////////
我先抛块砖,有玉的砸过来!
在何时何地,你都可以通过以下方法精确的得到任何一个对象(Application,DocTemplate,Document,View,Frame)
1。通过AfxGetApp()得到当前的App对象;
2。通过AfxGetMainWnd()得到主窗口;
3。通过CMDIFrameWnd::GetActiveFrame得到当前活动窗口;
4。通过GetNextWindow()遍例所有的子窗口;(如果要得到你想要的子窗口,可以通过特定的成员变量来标志);
5。通过CWinApp::GetFirstDocTemplatePostion()以及CWinApp::GetNextDocTemplate()的组合应用来遍历所有的DocTemplate对象,并且用CDocTemplate::GetDocString()来判断当前得到的文档莫板对象是哪个。
6。通过CDocTemplate::GetFirstDocPosition()以及CDocTemplate的GetNextDoc()组合来遍历所有的该模板的文档对象,并用CDocument::GetDocTemplate()来得到文档模板,用CDocment::GetTitle() 或者GetPathName()来判断当前的文档是哪个。
7。通过CDocuemt的GetFirstViewPositon()以及GetNextView()来遍历视图对象,一般通过访问View的成员变量来区别各个视图;通过CView::GetDocument()来得到文档对象;
8。Frame->View: 通过GetActiveView方法;
9。Frame->Doc:通过GetActiveDocument();
10。View->Frame:GetParentFrame();
11。View->Doc:GetDocuemt()//前面已经说了。
12。Doc->View:前面说了;
13。Doc->Frame:不知道有没有很直接的方法。
MFC应用程序中指针的使用
1) 在View中获得Doc指针
2) 在App中获得MainFrame指针
3) 在View中获得MainFrame指针
4) 获得View(已建立)指针
5) 获得当前文档指针
6) 获得状态栏与工具栏指针
7) 获得状态栏与工具栏变量
8) 在Mainframe获得菜单指针
9) 在任何类中获得应用程序类
10) 从文档类取得视图类的指针(1)
11) 在App中获得文档模板指针
12) 从文档模板获得文档类指针
13) 在文档类中获得文档模板指针
14) 从文档类取得视图类的指针(2)
15) 从一个视图类取得另一视图类的指针
VC中编程对于刚刚开始学习的同学,最大的障碍和问题就是消息机制和指针获取与
操作。其实这些内容基本上是每本VC学习工具书上必讲的内容,而且通过MSDN很多
问题都能解决。下面文字主要是个人在编程中指针使用的一些体会,说的不当的地
方请指正。一般我们使用的框架是VC提供的Wizard生成的MFC App Wizard(exe)框架,
无论是多文档还是单文档,都存在指针获取和操作问题。下面这节内容主要是一般
的框架,然后再讲多线程中的指针使用。使用到的类需要包含响应的头文件。首先
一般获得本类(视,文档,对话框都支持)实例指针this,用this的目的,主要可以通
过类中的函数向其他类或者函数中发指针,以便于在非本类中操作和使用本类中的
功能。
1) 在View中获得Doc指针 CYouSDIDoc *pDoc=GetDocument();一个视只能有一个文
档。
2) 在App中获得MainFrame指针
CWinApp 中的 m_pMainWnd变量就是MainFrame的指针
也可以: CMainFrame *pMain =(CMainFrame *)AfxGetMainWnd();
3) 在View中获得MainFrame指针 CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;
4) 获得View(已建立)指针 CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;
CyouView *pView=(CyouView *)pMain->GetActiveView();
5) 获得当前文档指针 CDocument * pCurrentDoc =(CFrameWnd *)m_pMainWnd->GetActiveDocument();
6) 获得状态栏与工具栏指针 CStatusBar * pStatusBar=(CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
CToolBar * pToolBar=(CtoolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);
7) 如果框架中加入工具栏和状态栏变量还可以这样
(CMainFrame *)GetParent()->m_wndToolBar;
(CMainFrame *)GetParent()->m_wndStatusBar;
8) 在Mainframe获得菜单指针 CMenu *pMenu=m_pMainWnd->GetMenu();
9) 在任何类中获得应用程序类
用MFC全局函数AfxGetApp()获得。
10) 从文档类取得视图类的指针
我是从http://download.cqcnc.com/soft/program/article/vc/vc405.html学到的,
从文档获得视图类指针目的一般为了控制同一文档的多个视图的定位问题,我的体会
特别是文字处理CEditView当产生多个视图类时,这个功能是非常需要的。
CDocument类提供了两个函数用于视图类的定位:
GetFirstViewPosition()和GetNextView()
virtual POSITION GetFirstViewPosition() const;
virtual CView* GetNextView(POSITION& rPosition) const;
注意:GetNextView()括号中的参数用的是引用方式,因此执行后值可能改变。
GetFirstViewPosition()用于返回第一个视图位置(返回的并非视图类指针,而是一
个POSITION类型值),GetNextView()有两个功能:返回下一个视图类的指针以及用
引用调用的方式来改变传入的POSITION类型参数的值。很明显,在Test程序中,只有
一个视图类,因此只需将这两个函数调用一次即可得到CTestView的指针如下(需定
义一个POSITION结构变量来辅助操作):
CTestView* pTestView;
POSITION pos=GetFirstViewPosition();
pTestView=GetNextView(pos);
这样,便可到了CTestView类的指针pTestView.执行完几句后,变量pos=NULL,因为没
有下一个视图类,自然也没有下一个视图类的POSITION.但是这几条语句太简单,不
具有太强的通用性和安全特征;当象前面说的那样,当要在多个视图为中返回某个指
定类的指针时,我们需要遍历所有视图类,直到找到指定类为止。判断一个类指针指
向的是否某个类的实例时,可用IsKindOf()成员函数时行检查,如:
pView->IsKindOf(RUNTIME_CLASS(CTestView));
即可检查pView所指是否是CTestView类。
有了以上基础,我们已经可以从文档类取得任何类的指针。为了方便,我们将其作
为一个文档类的成员函数,它有一个参数,表示要获得哪个类的指针。实现如下:
CView* CTestDoc::GetView(CRuntimeClass* pClass)
{
CView* pView;
POSITION pos=GetFirstViewPosition();
while(pos!=NULL){
pView=GetNextView(pos);
if(!pView->IsKindOf(pClass))
break;
}
if(!pView->IsKindOf(pClass)){
AfxMessageBox("Connt Locate the View.\r\n http://www.VCKBASE.com");
return NULL;
}
return pView;
}
其中用了两次视图类的成员函数IsKindOf()来判断,是因为退出while循环有三种
可能:
1.pos为NULL,即已经不存在下一个视图类供操作;
2.pView已符合要求。
1和2同是满足。这是因为GetNextView()的功能是将当前视图指针改变成一个视图
的位置同时返回当前视图指针,因此pos是pView的下一个视图类的POSITION,完全
有可能既是pos==NULL又是pView符合需要。当所需的视图是最后一个视图是最后一
个视图类时就如引。因此需采用两次判断。
使用该函数应遵循如下格式(以取得CTestView指针为例):
CTestView* pTestView=(CTestView*)GetView(RUNTIME_CLASS(CTestView));
RUNTIME_CLASS是一个宏,可以简单地理解它的作用:将类的名字转化为
CRuntimeClass为指针。至于强制类型转换也是为了安全特性考虑的,因为从同一个
基类之间的指针类型是互相兼容的。这种强制类型转换也许并不必要,但能避免一
些可能出现的麻烦。
3.从一个视图类取得另一视图类的指针综合1和2,很容易得出视图类之间互相获得
指针的方法:就是用文档类作中转,先用1的方法得到文档类的指针,再用2的方法,
以文档类的视图定位函数取得另一个视图类。同样,可以实现成一个函数:
(假设要从CTestAView中取得指向其它视图类的指针)
CView* CTestAView::GetView(CRuntimeClass* pClass)
{
CTestDoc* pDoc=(CTestDoc*)GetDocument();
CView* pView;
POSITION pos=pDoc->GetFirstViewPosition();
while(pos!=NULL){
pView=pDoc->GetNextView(pos);
if(!pView->IsKindOf(pClass))
break;
}
if(!pView->IsKindOf(pClass)){
AfxMessageBox("Connt Locate the View.");
return NULL;
}
return pView;
}
这个函数和2中的GetView()相比,一是多了第一句以取得文档类指针,二是在
GetFirstViewPosition()和GetNextView()前加上了文档类指针,以表示它们是文档
类成员函数。有了此函数;当要从CTestAView中取得CTestBView的指针时,只需如
下:CTestBView* pTestbView=(CTestView*)GetView(RUNTIME_CLASS(CTestBView));
11)对于单文档中也可以加入多个文档模板,但是一般的开发就使用MDI方式开发
多文档模板,其方法与上述视图的获取方法很接近,这里稍做解释,如果不清楚,
请查阅MSDN,(以下四个内容(11、12、13、14)来源:
http://sanjianxia.myrice.com/vc/vc45.htm)
可以用CWinApp::GetFirstDocTemplatePostion获得应用程序注册的第一个文档模板
的位置;利用该值来调用CWinApp::GetNextDocTemplate函数,获得第一个
CDocTemplate对象指针。 POSITION GetFirstDocTemplate( ) const;
CDocTemplate *GetNextDocTemplate( POSITION & pos ) const;
第二个函数返回由pos 标识的文档模板。POSITION是MFC定义的一个用于迭代或对象
指针检索的值。通过这两个函数,应用程序可以遍历整个文档模板列表。如果被检索
的文档模板是模板列表中的最后一个,则pos参数被置为NULL。
12)一个文档模板可以有多个文档,每个文档模板都保留并维护了一个所有对应文
档的指针列表。
用CDocTemplate::GetFirstDocPosition函数获得与文档模板相关的文档集合中第一
个文档的位置,并用POSITION值作为CDocTemplate::GetNextDoc的参数来重复遍历与
模板相关的文档列表。函数原形为:
viaual POSITION GetFirstDocPosition( ) const = 0;
visual CDocument *GetNextDoc(POSITION & rPos) const = 0;
如果列表为空,则rPos被置为NULL.
13)在文档中可以调用CDocument::GetDocTemplate获得指向该文档模板的指针。
函数原形如下: CDocTemplate * GetDocTemplate ( ) const;
如果该文档不属于文档模板管理,则返回值为NULL。
14)一个文档可以有多个视。每一个文档都保留并维护一个所有相关视的列表。
CDocument::AddView将一个视连接到文档上,将该视加入到文档相联系的视的列表
中,并将视的文档指针指向该文档。当有File/New、File/Open、Windows/New或
Window/Split的命令而将一个新创建的视的对象连接到文档上时, MFC会自动调用
该函数,框架通过文档/视的结构将文档和视联系起来。当然,程序员也可以根据自
己的需要调用该函数。
Virtual POSITION GetFirstViewPosition( ) const;
Virtual CView * GetNextView( POSITION &rPosition) cosnt;
应用程序可以调用CDocument::GetFirstViewPosition返回与调用文档相联系的视的
列表中的第一个视的位置,并调用CDocument::GetNextView返回指定位置的视,并将
rPositon的值置为列表中下一个视的POSITION值。如果找到的视为列表中的最后一个
视,则将rPosition置为NULL.
15)从一个视图类取得另一视图类的指针
这个应用在多视的应用程序中很多见,一般如果自己在主程序或者主框架中做好变
量记号,也可以获得,还有比较通用的就是用文档类作中转,以文档类的视图遍历
定位,取得另一个视图类。这个功能从本文第10项中可以得到。
posted @
2008-06-14 05:20 幽幽 阅读(868) |
评论 (0) |
编辑 收藏
#include <string> //使用C++标准库的string类时
using namespace std; //同上
#include <sstream>
#include <iostream>
#include <stdlib.h> //要将string类和int类型直接转换最好有这些包含,
//因为自己写一个转换函数比较方便,函数定义参考如下
string getstring ( const int n )
{
std::stringstream newstr;
newstr<<n;
return newstr.str();
}
string 转 CString
CString.format(”%s”, string.c_str());
char 转 CString
CString.format(”%s”, char*);
char 转 string
string s(char *);
string 转 char *
char *p = string.c_str();
CString 转 string
string s(CString.GetBuffer());
1,string -> CString
CString.format(”%s”, string.c_str());
用c_str()确实比data()要好.
2,char -> string
string s(char *);
只能初始化,在不是初始化的地方最好还是用assign().
3,CString -> string
string s(CString.GetBuffer());
GetBuffer()后一定要ReleaseBuffer(),否则就没有释放缓冲区所占的空间.
《C++标准函数库》中说的
有三个函数可以将字符串的内容转换为字符数组和C—string
1.data(),返回没有”\0“的字符串数组
2,c_str(),返回有”\0“的字符串数组
3,copy()
—————————————————————
CString与int、char*、char[100]之间的转换- -
CString与int、char*、char[100]之间的转换- -
CString互转int
将字符转换为整数,可以使用atoi、_atoi64或atol。
而将数字转换为CString变量,可以使用CString的Format函数。如
CString s;
int i = 64;
s.Format(”%d”, i)
Format函数的功能很强,值得你研究一下。
void CStrDlg::OnButton1()
{
// TODO: Add your control notification handler code here
CString
ss=”1212.12″;
int temp=atoi(ss);
CString aa;
aa.Format(”%d”,temp);
AfxMessageBox(”var is ” + aa);
}
sart.Format(”%s”,buf);
CString互转char*
///char * TO cstring
CString strtest;
char * charpoint;
charpoint=”give string a value”;
strtest=charpoint;
///cstring TO char *
charpoint=strtest.GetBuffer(strtest.GetLength());
标准C里没有string,char *==char []==string
可以用CString.Format(”%s”,char *)这个方法来将char *转成CString。要把CString转成char *,用操作符(LPCSTR)CString就可以了。
CString转换 char[100]
char a[100];
CString str(”aaaaaa”);
strncpy(a,(LPCTSTR)str,sizeof(a));
posted @
2008-06-14 05:11 幽幽 阅读(45712) |
评论 (4) |
编辑 收藏