Netbeans中文乱码问题汇总(转)

Netbeans中文乱码问题汇总(转)

转载地址:http://blog.csdn.net/luntan6788/archive/2008/07/14/2651318.aspx
最近刚刚开始用Netbeans,就遇到了最容易遇到的中文乱码问题。(好像从Eclipse,到JBuilder再到Netbeans,都需要解决这类 问题)于是在网上查找了一下,这里给出一个常见的中文乱码问题汇总。呵呵。
最常见的,源程序导入Netbeans中以后,其中的注释或字符串成了乱码。
这个问题好解决也不好解决。Netbeans是可以设置工程的文件编码格式的。在你的工程上点右键,Properties选项中Sources里面可以设 置编码格式。比Eclipse强的一点是这里有很多种编码格式可以选择,我需要用的GBK也在。不象当年用Eclipse的时候就下拉列表里面的编码那么 几种,到处找不到GBK。后来查了一下才知道,那个ComboBox不止可以选,自己写一个GBK上去也可以,然后就支持GBK了。晕倒,怎么有这么设计 的。说这个问题不好解决的原因就是需要你原来文件的编码格式没有问题,比如是GBK的,或者UTF的,或者其他的,总之需要Netbeans支持的。我见 到一个哥们问,他的文件(同一个文件)里面又有中文GBK,又有日文,怎么支持。没办法,支持不了。另外需要注意的是如果文件已经打开了,那么改工程编码 不会自动刷新的。需要关了再开一次。我开始就没明白。
我遇到的问题是文件里面的内容没问题,但是运行后Netbeans的控制台里面是乱码。Eclipse里面可以设置控制台编码格式的,但是我在 Netbeans里面没找到。用程序的命令行参数-encoding GBK也不起作用。后来找了各种方法来试,发现需要在Netbeans的安装目录下的etc目录下有一个netbeans.conf,其中有 Netbeans的启动参数:netbeans_default_options=”-J-Dcom.sun.aas.installRoot=”C: Program Filesglassfish-v2ur2″ -J-client -J-Xss2m -J-Xms32m -J-XX:PermSize=32m -J-XX:MaxPermSize=200m -J-Xverify:none -J-Dapple.laf.useScreenMenuBar=true -J-Dsun.java2d.noddraw=true “。在启动参数中增加编码方式的设置netbeans_default_options=”-J-Dcom.sun.aas.installRoot= “C:Program Filesglassfish-v2ur2” -J-client -J-Xss2m -J-Xms32m -J-XX:PermSize=32m -J-XX:MaxPermSize=200m -J-Xverify:none -J-Dapple.laf.useScreenMenuBar=true -J-Dsun.java2d.noddraw=true -J-Dfile.encoding=GBK“, 这样Netbeans的控制台就可以显示正常的中文了。
另外一个在网上见到大家讨论最多的乱码问题就是在Ubuntu下中文都显示成方框的问题,是由于没有合适的中文字体文件造成的。解决方法如下:在 /user/share/fonts目录下找到gbsn00lp.ttf,把它拷到 javahome/jre/lib/fonts/fallback下面。一般,jre里没有fallback目录,你需要建一个。然后再打开 netbeans等同样用java环境的软件,界面方块问题就不会再有了。有些版本的Ubuntu下没有这个字体文件,解决办法是把 /usr/share/fonts/truetype/arphic/ 文件夹下的字体拷贝到 JAVA_HOME/jre/lib/fonts/fallback下面,就OK了。
=======================
我修除windows下netbeans 6.0 C/C++乱码的过程:首先是在项目上点击右键,选择好编码。如果原先的文件已经生成过了,则需要在所有的中文处(这个时候可能已经是乱码了),重新输入 中文。这样,察看结果的时候,就不会有乱码了。

在MFC中添加用户自定义消息【转载】

# 在MFC中添加用户自定义消息【转载】 转载地址: http://blog.sina.com.cn/s/blog\_4a1695ff0100ckgo.html\  \ 首先弄清楚两点:\ (1)谁要发送这个消息(2)谁要接受这个消息。\ 用一个简单的例子来说明。对象A向B(也可以就是A到A)发送消息。\ 1 发送消息\ 首先在A的头文件中定义这个消息:\ #define WM\_USERMESSAGE WM\_USER+30\ 所有自定义消息都是以WM\_USER消息为基础加上一个任意的自然数来表示的。A是向外发送消息的对象,因此在A的某个方法(函数)里就会调用用来发消 息的函数B::SendMessage()/B::PostMessage(),因为是B接受消息,因此是如上的形式。\ \ 2 接受消息\ 对象接受一个消息,应该有三部分:在头文件中有该消息的处理函数的原型;在实现文件中有接受消息映射的宏; 以及该消息的处理函数的具体实现。\ 2.1 头文件中加上自定义消息的处理函数原型\ 在DECLARE\_MESSAGE\_MAP()语句之前,一对AFX\_MSG之间加上如下形式的函数原型:\ afx\_msg LRESULT OnProcName( WPARAM wParam, LPARAM lParam );\ 对Win32来说,wParam, lParam是传递消息最常用的手段。\ 2.2 在实现文件中加上接受消息映射的宏\ 在cpp文件里,BEGIN\_MESSAGE\_MAP语句之后,在一对AFX\_MSG\_MAP之间,增加 如下形式的代码:\ ON\_MESSAGE(WM\_USERMESSAGE, OnProcName)\ 上面是不用分号结尾的。\ 2.3 在实现文件中给出消息处理函数的具体实现。\ 发信人: Amia (小羊·橘子·和中南海有缘), 信区: VisualC\ 标 题: MFC中自由使用自定义消息\ 发信站: 哈工大紫丁香 (2003年11月26日07:45:34 星期三), 站内信件\ \ 消息映射、循环机制是Windows程序运行的基本方式。VC++ MFC 中有许多现成的消息句柄\ ,可当我们需要完成其它的任务,需要自定义消息,就遇到了一些困难。在MFC  \ ClassWizard中不允许添加用户自定义消息,所以我们必须在程序中添加相应代码,以便可\ 以象处理其它消息一样处理自定义消息。通常的做法是采取以下步骤:\ \ 第一步:定义消息。\ \ 推荐用户自定义消息至少是WM\_USER+100,因为很多新控件也要使用WM\_USER消息。\ \ #define WM\_MY\_MESSAGE (WM\_USER+100)  \ \ 第二步:实现消息处理函数。该函数使用WPRAM和LPARAM参数并返回LPESULT。  \ \ LPESULT CMainFrame::OnMyMessage(WPARAM wParam, LPARAM lParam)  \ {  \ // TODO: 处理用户自定义消息  \ …  \ return 0;  \ }  \ \ 第三步:在类头文件的AFX\_MSG块中说明消息处理函数:\ \ class CMainFrame:public CMDIFrameWnd  \ {  \ …  \ // 一般消息映射函数  \ protected:  \ // {{AFX\_MSG(CMainFrame)  \ afx\_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);  \ afx\_msg void OnTimer(UINT nIDEvent);  \ afx\_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);  \ //}}AFX\_MSG  \ DECLARE\_MESSAGE\_MAP()  \ }  \ \ 第四步:在用户类的消息块中,使用ON\_MESSAGE宏指令将消息映射到消息处理函数中。\ \ \ BEGIN\_MESSAGE\_MAP(CMainFrame, CMDIFrameWnd)  \ //{{AFX\_MSG\_MAP(CMainFrame)  \ ON\_WM\_CREATE()  \ ON\_WM\_TIMER()  \ ON\_MESSAGE(WM\_MY\_MESSAGE, OnMyMessage)  \ //}}AFX\_MSG\_MAP  \ END\_MESSAGE\_MAP()  \ \ 如果用户需要一个定义整个系统唯一的消息,可以调用SDK函数RegisterWindowMessage定义\ 消息:\ \ static UINT WM\_MY\_MESSAGE=RegisterWindowMessage(“User”);  \ \ 并使用ON\_REGISTERED\_MESSAGE宏指令取代ON\_MESSAGE宏指令,其余步骤同上。\ \ 当需要使用自定义消息时,可以在相应类中的函数中调用函数PostMessage或SendMessa\ ge发送消息PoseMessage(WM\_MY\_MESSAGE,O,O); 如果向其他进程发送消息可通过如下方法\ 发送消息:\ \ DWORD result;\ SendMessageTimeout(wnd->m\_hWnd, // 目标窗口\ WM\_MY\_MESSAGE, // 消息\ 0, // WPARAM\ 0, // LPARAM\ SMTO\_ABORTIFHUNG |\ SMTO\_NORMAL,\ TIMEOUT\_INTERVAL,\ &result);  \ \ 以避免其它进程如果被阻塞而造成系统死等状态。\ \ 可是如果需要向其它类(如主框架、子窗口、视类、对话框、状态条、工具条或其他控\ 件等)发送消息时,上述方法显得无能为力,而在编程过程中往往需要获取其它类中的某个\ 识别信号,MFC框架给我们造成了种种限制,但是可以通过获取某个类的指针而向这个类发送\ 消息,而自定义消息的各种动作则在这个类中定义,这样就可以自由自在的向其它类发送\ 消息了。\ \ 下面举的例子叙述了向视类和框架类发送消息的方法:\ \ 在主框架类中向视类发送消息:\ \ 视类中定义消息:\ \ ON\_REGISTERED\_MESSAGE(WM\_MY\_MESSAGE,OnMyMessage) //定义消息映射\ 视类定义消息处理函数:\ \ // 消息处理函数\ LRESULT CMessageView::OnMyMessage(WPARAM wParam, LPARAM lParam)\ {\ // TODO: 处理用户自定义消息  \ …  \ return 0;\ }  \ \ //发送消息的测试函数\ void CMainFrame::OnTest()\ {\ CView \* active = GetActiveView();//获取当前视类指针\ if(active != NULL)\ active->PostMessage(WM\_MY\_MESSAGE,0,0);\ }  \ \ 在其它类中向视类发送消息:\ \ //发送消息的测试函数\ void CMainFrame::OnTest()\ {\ CMDIFrameWnd \*pFrame;\ CMDIChildWnd \*pChild;\ CView \*pView;\ //获取主窗口指针\ pFrame =(CMDIFrameWnd\*)AfxGetApp()->m\_pMainWnd;\ // 获取子窗口指针\ pChild = (CMDIChildWnd \*) pFrame->GetActiveFrame();\ //获取视类指针\ pView = pChild->GetActiveView();\ if(pView != NULL)\ pView->PostMessage(WM\_MY\_MESSAGE,0,0);//发送消息\ }  \ \ 其余步骤同上。\ \ 在视类中向主框架发送消息:\ \ 首先在主框架中定义相关的消息,方法同上,然后在发送消息的函数中添加代码如下\ \ //发送消息的测试函数\ void CMessageView::OnTest()\ {\ CFrameWnd \* active = GetActiveFrame();//获取当前主窗口框架指针\ if(active != this)\ active->PostMessage(WM\_MY\_MESSAGE,0,0);\ return 0;\ }  \ \ 在其它类中向不同的类发送消息可依次方法类推,这样我们的程序就可以的不受限制\ 向其它类和进程发送消息,而避免了种种意想不到的风险。\ \ 下面一个例子程序为多文档程序里在一对话框中向视类发送消息,详述了发送自定义消\ 息的具体过程。\ 实现步骤:\ \ 第一步:在VC++中新建工程Message,所有ClassWizard步骤选项均为缺省,完成。\ \ 第二步:在主菜单中添加测试菜单为调出对话框,在框架类中建立相应函数OnTest()\ \ 第三步:在资源中建立对话框,通过ClassWizard添加新类TestDialog,添加测试按钮,\ \ \ 在对话框类中建立相应函数OnDialogTest()\ \ //通过对话框按钮发送消息的函数\ void TestDialog::OnDialogTest()\ {\ CMDIFrameWnd \*pFrame;\ CMDIChildWnd \*pChild;\ CView \*pView;\ //获取主窗口指针\ pFrame =(CMDIFrameWnd\*)AfxGetApp()->m\_pMainWnd;\ // 获取子窗口指针\ pChild = (CMDIChildWnd \*) pFrame->GetActiveFrame();\ //获取视类指针\ pView = pChild->GetActiveView();\ if(active != NULL)\ active->PostMessage(WM\_MY\_MESSAGE,0,0);//发送消息\ }  \ \ 在Message.h头文件中添加如下语句:\ \ static UINT WM\_MY\_MESSAGE=RegisterWindowMessage(“Message”);  \ \ 第四步:在视类中添加自定义消息:\ \ 在头文件MessageView.h中添加消息映射\ \ protected:\ //{{AFX\_MSG(CMessageView)\ //}}AFX\_MSG\ afx\_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam); //此行为添加代码\ DECLARE\_MESSAGE\_MAP()\ 在视类文件MessageView.cpp中的消息映射中添加自定义消息映射\ BEGIN\_MESSAGE\_MAP(CMessageView, CView)\ //{{AFX\_MSG\_MAP(CMessageView)\ //}}AFX\_MSG\_MAP\ // Standard printing commands\ ON\_REGISTERED\_MESSAGE(WM\_MY\_MESSAGE,OnMyMessage) //此行添加代码定义唯一消息\ END\_MESSAGE\_MAP()  \ \ 添加相应的0消息处理函数\ \ LRESULT CMessageView::OnMyMessage(WPARAM wParam, LPARAM lParam)\ {\ CRect rect;\ GetClientRect(&rect);\ InvalidateRect(&rect);\ test=!test;\ return 0;\ }  \ \ 在MessageView.h中添加布尔变量 public:BOOL test;\ \ 在视类构造函数中初始化 test变量:test=FALSE;\ \ 修改CMessageView::OnDraw()函数\ \ void CMessageView::OnDraw(CDC\* pDC)\ {\ CMessageDoc\* pDoc = GetDocument();\ ASSERT\_VALID(pDoc);\ // 以下程序显示消息响应效果\ if(test)\ pDC->TextOut(0,0,”消息响应!”);\ }  \ \ 第五步:显示测试对话框\ \ 在MainFrame类中包含对话框头文件:\ \ #include “TestDialog.h”;\ OnTest()函数中添加代码\ void CMainFrame::OnTest()\ {\ TestDialog dialog;\ dialog.DoModal();\ }  \ \ 运行程序,在测试菜单打开对话框,点击测试按钮即可看到结果。

用Visio画ER图的解决方案(转载)

用Visio画ER图的解决方案(转载)

转自:http://hi.baidu.com/%BA%EC%C3%F1/blog/item/d013f603726e0c8ad53f7c78.html\
今天刚刚装了Visio,但是郁闷地发现Visio中默认没有ER图的模型,绘图类型中的数据库模型中也没有ER图,根本没有菱形。对于第一次接触 Visio的我来说花了好大的力气也没有找到,想专业一把未遂。
后来问了其他人,答案更让当时郁闷的我有些火气:1)菱形在基本流程图里(晕,那也不是ER图中的啊,怎么能这么混用啊,不伦不类)2)你就将就一下嘛, 画出来就行,那么专业干嘛?(更晕,要是不想画的专业我就不花力气用Visio了)。其实想想,他们是比我懂得变通的,我怎么就这么死心眼儿呢?还是有点 儿完美主义?我不知道,但是我没有采纳他们的意见,继续找我自己的解决方式。记得好像有相关的模版或者模型可以下载的,但是没有找到。再后来,我对 Visio熟悉了一些,自己选择了这样一种解决方式:自定义。
先在“流程图”-〉“基本流程图”中找到菱形和方块,分别右击选择“添加到我的形状”-〉“添加到新模具”。之后出现“另存 为”对话框,把新模具命名为“ER图”,这样我们就把菱形和方块添加到了新模具“ER图”中。用同样的思路,在“数据库”-〉“ORM图表”找到椭圆和直 线,添加到模具“ER图”中。
添加完成后,我们就可以在画ER图时打开该模具,ER图所有的元素都会在一个模具中显示出来了。

MFC指针的获取(转载)

MFC指针的获取(转载)

源地址:http://blog.csdn.net/yincheng01/archive/2009/01/06/3718954.aspx

1、获取应用程序指针
CMyApp* pApp=(CMyApp*)AfxGetApp();
2、获取主框架指针
CWinApp 中的公有成员变量 m_pMainWnd 就是主框架的指针
CMainFrame* pMainFrame = (CMainFrame*)(AfxGetApp()->m_pMainWnd);
或者
CMainFrame* pMainFrame = (CMainFrame*)AfxGetMainWnd();
3、获取菜单指针
CMenu* pMenu = AfxGetMainWnd()->GetMenu();
4、获取工具栏、状态栏指针
主框架中可以直接使用m_wndToolBar、m_wndStatusBar
其他:
CToolBar* pToolBar = (CToolBar*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);
CStatusBar* pStatusBar = (CStatusBar*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
5、获取控件指针
先用 GetDlgItem() 再转换,如:
CButton* pButton = (CButton*)GetDlgItem(IDC_MYBUTTON);
6、获取文档、视图指针

SDI:
CMainFrame* pMainFrame = (CMainFrame*)AfxGetMainWnd();
CYourDoc* pDoc = (CYourDoc*)pMainFrame->GetActiveDocument();
CYourView* pView = (CYourView*)pMainFrame->GetActiveView();
MDI:
CMainFrame* pMainFrame = (CMainFrame*)AfxGetMainWnd();
CChildFrame* pChildFrame = (CChildFrame*)pMainFrame->GetActiveFrame();
CYourDoc* pDoc = (CYourDoc*)pChildFrame->GetActiveDocument();
CYourView* pView = (CYourView*)pChildFrame->GetActiveView();

7、文档、视图

从视图获取文档指针:
CYourDoc* pDoc = GetDocument();
从文档获取视图指针:
利用成员函数 GetFirstViewPosition() 和 GetNextView() 遍历
virtual POSITION GetFirstViewPosition() const;
virtual CView* GetNextView(POSITION& rPosition) const;
SDI:
CYourView* pView;
POSITION pos = GetFirstViewPosition();
pView = GetNextView(pos);
MDI:
定义函数
CView* CYourDoc::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.”);
return NULL;
}
return pView;
}
使用如下:
CYourView* pView=(CYourView*)GetView(RUNTIME_CLASS(CYourView));

8、文档模版、文档

从文档获取文档模版指针:
CDocTemplate* GetDocTemplate() const;
从文档模版获取文档指针:
viaual POSITION GetFirstDocPosition( ) const = 0;
visual CDocument* GetNextDoc(POSITION & rPos) const = 0;

9、获取分割视图中各个视图的指针

主框架中定义:CSplitterWnd m_wndSplitter;

定义两个View:CView1、CView2

框架中重载:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext)
{
VERIFY(m_splitter.CreateStatic(this,2,1)); //分割成两行一列
VERIFY(m_splitter.CreateView(0,0,RUNTIME_CLASS(CView1),CSize(100,100),pContext));
VERIFY(m_splitter.CreateView(1,0,RUNTIME_CLASS(CView2),CSize(100,100),pContext));
return TRUE;
}

获取分割视图指针
CView1* pView1 = (CView1*)m_wndSplitter.GetPane(0,0);
CView2* pView2 = (CView2*)m_wndSplitter.GetPane(1,0);

10、通过鼠标获得子窗口指针

CWnd* ChildWindowFromPoint(POINT point) const;
CWnd* ChildWindowFromPoint(POINT point,UINT nFlags) const;
用于确定包含指定点的子窗口
如 果指定点在客户区之外,函数返回NULL;
如果指定点在客户区内,但是不属于任何一个子窗口,函数返回该CWnd的指针;
如果有多个子窗 口包含指定点,则返回第一个子窗口的指针。
还要注意的是,该函数返回的是一个伪窗口指针,不能将它保存起来供以后使用。
对于第二个参数 nFlags有几个含义:
CWP_ALL             file://不忽略任何子窗口
CWP_SKIPNIVSIBLE    file://忽略不可见子窗口
CWP_SKIPDISABLED    file://忽略禁止的子窗口
CWP_SKIPRANSPARENT file://忽略透明子窗口

获 取工具条的指针
在缺省状态下,有一个默认的工具条AFX_IDW_TOOLBAR, 我们可以根据相应的ID去获取工具条指针,方法如下:
CToolBar* pToolBar=(CToolBar*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);
是不是很简单?
获取状态条的指 针
在缺省状态下,有一个默认的状态条AFX_IDW_STATUS_BAR, 我们自然也可以根据相应的ID去获取状态条指针,方法如下:
CStatusBar* pToolBar=(CStatusBar*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
是不是同样很简单?
    获取控件的指针
这里有两种方法。
一、调用CWnd: : GetDlgItem, 获取一个CWnd*指针调用成员函数。例如,我们想获取CButton指针,方法如下:
CButton* pButton=(CButton*) GetDlgItem (IDC_MYBUTTON);
二、可以使用ClassWizard将控件和成员变量联系起来。在ClassWizard中 简单地选择Member Variables标签,然后选择Add Variable …按钮。如 果在对话资源编辑器中,按下Ctrl键并双击控件即可转到Add Member Variable对 话。
    在文档类中调用 视图类指针
我们可以利用文档类的成员函数GetFirstView()和GetNextView()遍 历视图。
    在视图类中调用文档类
其实,在视图类中有一个现成的成员函数供我们使用,那就是:GetDocument();利 用它我们可以很容易的得到文档类指针,我们先看一下GetDocument()函数的实现:
CColorButtonDoc* CColorButtonView::GetDocument()
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CColorButtonDoc)));
return (CColorButtonDoc*)m_pDocument;
}
这里实际上是将m_pDocument强制转换成CColorButtonDoc*, 也就是我们想要的。
   在框架类中调 用文档类、视图类
这里我们可以利用GetActiveXXXXX()去 掉用当前激活的文档和视图:
CMyDoc*   pDoc=(CMyDoc*)GetActiveDocument();
CMyView* pView=(CMyView*)GetActiveView();
   获得应用程序指针
这个很简单,一句话搞定:
CMyApp* pApp=(CMyApp*)AfxGetApp();
   获得主框架指 针
在类CWinThread里面有一个公有 的成员变量:CWnd* m_pMainWnd; 它存在的主要目的就是提供我们获得CWnd指 针,我们可以利用它来达到我们的目的:
CMainFrame* pFrame=(CMainFrame*)(AfxGetApp()->m_pMainWnd);
通过鼠标获 得子窗口指针
这里我们要用到一个不太常用的函数:ChildWindowFromPoint。 他的原型如下:
CWnd* ChildWindowFromPoint(POINT point) const;
CWnd* ChildWindowFromPoint(POINT point,UINT nFlags) const;
这个函数用于确定包含指定点的子窗口,如果指定点在客户区之外,函数返回NULL;如果指定点在客户区 内,但是不属于任何一个子窗口,函数返回该CWnd的指针;如果有多个子窗口包含指定点,则返回第一个子窗口的指针。不过,这 里还要注意的是:该函数返回的是一个伪窗口指针,不能将它保存起来供以后使用。
对于第二个参数nFlags有几个含义:
CWP_ALL             file://不忽略任何子窗口
CWP_SKIPNIVSIBLE    file://忽略不可见子窗口
CWP_SKIPDISABLED    file://忽略禁止的子窗口
CWP_SKIPRANSPARENT  file://忽略 透明子窗口

在何时何地,你都可以通过以下方法精确的得到任何一个对象 (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();一个视只能有一个文
    档。\
  16. 在App中获得MainFrame指针
    CWinApp 中的 m_pMainWnd变量就是MainFrame的指针
    也可以: CMainFrame *pMain =(CMainFrame *)AfxGetMainWnd();\
  17. 在View中获得MainFrame指针 CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;\
  18. 获得View(已建立)指针 CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;
    CyouView *pView=(CyouView *)pMain->GetActiveView();\
  19. 获得当前文档指针 CDocument * pCurrentDoc =(CFrameWnd *)m_pMainWnd->GetActiveDocument();\
  20. 获得状态栏与工具栏指针 CStatusBar * pStatusBar=(CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
    CToolBar * pToolBar=(CtoolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);\
  21. 如果框架中加入工具栏和状态栏变量还可以这样
    (CMainFrame *)GetParent()->m_wndToolBar;
    (CMainFrame *)GetParent()->m_wndStatusBar;\
  22. 在Mainframe获得菜单指针 CMenu *pMenu=m_pMainWnd->GetMenu();\
  23. 在任何类中获得应用程序类
    用MFC全局函数 AfxGetApp()获得。\
  24. 从文档类取得视图类的指针
    我是从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.rn 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));
    对于单文档中也可以加 入多个文档模板,但是一般的开发就使用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.\
  25. 从一个视图类取得另一视图类的指针
    这个应用在多视的应用程序中很多见,一般如果自己在主程序或者主框架中做好变
    量记号,也可以获得,还有 比较通用的就是用文档类作中转,以文档类的视图遍历
    定位,取得另一个视图类。这个功能从本文第10项中可以得到。

_RecordsetPtr的 open函数(转载)

_RecordsetPtr的 open函数(转载)

转自:http://hi.baidu.com/ruiqing\_2008/blog/item/50381334c10183bbd1a2d369.html\
_RecordsetPtr m_pRecordset;//创建一个_RecordsetPtr m_pRecordset.CreateInstance(“ADODB.Recordset”); //创建一个实例 try {      m_pRecordset->Open(
“SELECT * FROM duty”,                                               //sql查询语句
m_pConnection.GetInterfacePtr(),                               //得到sql连接的指针
//Const adOpenDynamic = 2 ‘动态游标功能最强,但耗资源也最多。用户对记录说做的修改,增加或删除记录都将反映到记录集中。支持全功能浏览(ACCESS不支持)。
adOpenDynamic,

//Const adLockOptimistic = 3 ‘只有在调用Update方法时才锁定记录集,而在此前的其他操作仍可对当前记录进行更改、插入和删除 等
adLockOptimistic,
//AdCmdText 将 CommandText 作为命令或存储过程调用的文本化定义进行计算。
adCmdText);
}
catch(_com_error e)
{
//cout<ErrorMessage()<<endl;
AfxMessageBox(“Create Instance failed!”);
return;
}

内容一:
‘定义数据库连接的一些常量
Const adOpenForwardOnly = 0 ‘(默认值)游标只向前浏览记录,不支持分页、Recordset、BookMark
Const adOpenKeyset = 1 ‘键集游标,其他用户对记录说做的修改将反映到记录集中,但其他用户增加或删除记录不会反映到记录集中。支持分页、Recordset、BookMark
Const adOpenDynamic = 2 ‘动态游标功能最强,但耗资源也最多。用户对记录说做的修改,增加或删除记录都将反映到记录集中。支持全功能浏览(ACCESS不支持)。
Const adOpenStatic = 3 ‘静态游标,只是数据的一个快照,用户对记录说做的修改,增加或删除记录都不会反映到记录集中。支持向前或向后移动
Const adLockReadOnly = 1 ‘(默认值)锁定类型,默认的,只读,不能作任何修改
Const adLockPessimistic = 2 ‘当编辑时立即锁定记录,最安全的方式
Const adLockOptimistic = 3 ‘只有在调用Update方法时才锁定记录集,而在此前的其他操作仍可对当前记录进行更改、插入和删除等
Const adLockBatchOptimistic = 4 ‘当编辑时记录不会被锁定,而更改、插入和删除是在批处理方式下完成的
Const adCmdText = &H0001
Const adCmdTable = &H0002
%>
Open 方法 (ADO Recordset)
打开游标。
语法
recordset.Open Source, ActiveConnection, CursorType, LockType, Options
内容二:
CommandType 属性
指示 Command 对象的类型。
设置和返回值
设置或返回以下某个 CommandTypeEnum 值。
常量 说明
AdCmdText 将 CommandText 作为命令或存储过程调用的文本化定义进行计算。
AdCmdTable 将 CommandText 作为其列全部由内部生成的 SQL 查询返回的表格的名称进行计算。
AdCmdTableDirect 将 CommandText 作为其列全部返回的表格的名称进行计算。
AdCmdStoredProc 将 CommandText 作为存储过程名进行计算。
AdCmdUnknown 默认值。CommandText 属性中的命令类型未知。
adCmdFile 将 CommandText 作为持久 Recordset 文件名进行计算。
AdExecuteNoRecords 指示 CommandText 为不返回行的命令或存储过程(例如,插入数据的命令)。如果检索任意行,则将丢弃这些行且并不返回。它总是与 adCmdText 或 adCmdStoredProc 进行组合。
说明
使用 CommandType 属性可优化 CommandText 属性的计算。
如果 CommandType 属性的值等于 adCmdUnknown(默认值),系统的性能将会降低,因为 ADO 必须调用提供者以确定 CommandText 属性是 SQL 语句、还是存储过程或表格名称。如果知道正在使用的命令的类型,可通过设置 CommandType 属性指令 ADO 直接转到相关代码。如果 CommandType 属性与 CommandText 属性中的命令类型不匹配,调用 Execute 方法时将产生错误。
adExecuteNoRecords 常量通过最小化内部处理来提高性能。该常量不独立使用,它总是与 adCmdText 或 adCmdStoredProc 组合(如 adCmdText+adExecuteNoRecords) 一起使用。如果与 Recordset.Open 一起使用 adExecuteNoRecords,或者该方法使用 Command 对象都将产生错误。

引用MFC指针的获取(转载)

引用MFC指针的获取(转载)


 
转自:http://hi.baidu.com.sixxs.org/eagle\_shuai/blog/item/325c3abfb763800619d81f90.html\
chilli 的 MFC指针的获取

1、获取应用程序指针
CMyApp* pApp=(CMyApp*)AfxGetApp();
2、获取主框架指针
CWinApp 中的公有成员变量 m_pMainWnd 就是主框架的指针
CMainFrame* pMainFrame = (CMainFrame*)(AfxGetApp()->m_pMainWnd);
或者
CMainFrame* pMainFrame = (CMainFrame*)AfxGetMainWnd();

3、获取菜单指针
CMenu* pMenu = AfxGetMainWnd()->GetMenu();
4、获取工具栏、状态栏指针
主框架中可以直接使用m_wndToolBar、m_wndStatusBar
其他:
CToolBar* pToolBar = (CToolBar*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);
CStatusBar* pStatusBar = (CStatusBar*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
5、获取控件指针
先用 GetDlgItem() 再转换,如:
CButton* pButton = (CButton*)GetDlgItem(IDC_MYBUTTON);
6、获取文档、视图指针
SDI:
CMainFrame* pMainFrame = (CMainFrame*)AfxGetMainWnd();
CYourDoc* pDoc = (CYourDoc*)pMainFrame->GetActiveDocument();
CYourView* pView = (CYourView*)pMainFrame->GetActiveView();
MDI:
CMainFrame* pMainFrame = (CMainFrame*)AfxGetMainWnd();
CChildFrame* pChildFrame = (CChildFrame*)pMainFrame->GetActiveFrame();
CYourDoc* pDoc = (CYourDoc*)pChildFrame->GetActiveDocument();
CYourView* pView = (CYourView*)pChildFrame->GetActiveView();
7、文档、视图
从视图获取文档指针:
CYourDoc* pDoc = GetDocument();
从文档获取视图指针:
利用成员函数 GetFirstViewPosition() 和 GetNextView() 遍历
virtual POSITION GetFirstViewPosition() const;
virtual CView* GetNextView(POSITION& rPosition) const;
SDI:
CYourView* pView;
POSITION pos = GetFirstViewPosition();
pView = GetNextView(pos);
MDI:
定义函数
CView* CYourDoc::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.”);
return NULL;
}
return pView;
}
使用如下:
CYourView* pView=(CYourView*)GetView(RUNTIME_CLASS(CYourView));
8、文档模版、文档
从文档获取文档模版指针:
CDocTemplate* GetDocTemplate() const;
从文档模版获取文档指针:
viaual POSITION GetFirstDocPosition( ) const = 0;
visual CDocument* GetNextDoc(POSITION & rPos) const = 0;
9、获取分割视图中各个视图的指针
主框架中定义:CSplitterWnd m_wndSplitter;
定义两个View:CView1、CView2
框架中重载:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext)
{
VERIFY(m_splitter.CreateStatic(this,2,1)); //分割成两行一列
VERIFY(m_splitter.CreateView(0,0,RUNTIME_CLASS(CView1),CSize(100,100),pContext));
VERIFY(m_splitter.CreateView(1,0,RUNTIME_CLASS(CView2),CSize(100,100),pContext));
return TRUE;
}
获取分割视图指针
CView1* pView1 = (CView1*)m_wndSplitter.GetPane(0,0);
CView2* pView2 = (CView2*)m_wndSplitter.GetPane(1,0);
10、通过鼠标获得子窗口指针
CWnd* ChildWindowFromPoint(POINT point) const;
CWnd* ChildWindowFromPoint(POINT point,UINT nFlags) const;
用于确定包含指定点的子窗口
如果指定点在客户区之外,函数返回NULL;
如果指定点在客户区内,但是不属于任何一个子窗口,函数返回该CWnd的指针;
如果有多个子窗口包含指定点,则返回第一个子窗口的指针。
还要注意的是,该函数返回的是一个伪窗口指针,不能将它保存起来供以后使用。
对于第二个参数nFlags有几个含义:
CWP_ALL             file://不忽略任何子窗口
CWP_SKIPNIVSIBLE    file://忽略不可见子窗口
CWP_SKIPDISABLED    file://忽略禁止的子窗口
CWP_SKIPRANSPARENT file://忽略透明子窗口
获取工具条的指针
在缺省状态下,有一个默认的工具条AFX_IDW_TOOLBAR,我们可以根据相应的ID去获取工具条指针,方法如下:
CToolBar* pToolBar=(CToolBar*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);
是不是很简单?
获取状态条的指针
在缺省状态下,有一个默认的状态条AFX_IDW_STATUS_BAR,我们自然也可以根据相应的ID去获取状态条指针,方法如下:
CStatusBar* pToolBar=(CStatusBar*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
这里有两种方法。
一、调用CWnd: : GetDlgItem,获取一个CWnd*指针调用成员函数。例如,我们想获取CButton指针,方法如下:
CButton* pButton=(CButton*) GetDlgItem (IDC_MYBUTTON);
二、可以使用ClassWizard将控件和成员变量联系起来。在ClassWizard中简单地选择Member Variables标签,然后选择Add Variable …按钮。如果在对话资源编辑器中,按下Ctrl键并双击控件即可转到Add Member Variable对话。
我们可以利用文档类的成员函数GetFirstView()和GetNextView()遍历视图。
其实,在视图类中有一个现成的成员函数供我们使用,那就是:GetDocument();利用它我们可以很容易的得到文档类指针,我们先看一下 GetDocument()函数的实现:
CColorButtonDoc* CColorButtonView::GetDocument()
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CColorButtonDoc)));
return (CColorButtonDoc*)m_pDocument;
}
这里实际上是将m_pDocument强制转换成CColorButtonDoc*,也就是我们想要的。
这里我们可以利用GetActiveXXXXX()去掉用当前激活的文档和视图:
CMyDoc*   pDoc=(CMyDoc*)GetActiveDocument();
CMyView* pView=(CMyView*)GetActiveView();
这个很简单,一句话搞定:
CMyApp* pApp=(CMyApp*)AfxGetApp();
在类CWinThread里面有一个公有的成员变量:CWnd* m_pMainWnd; 它存在的主要目的就是提供我们获得CWnd指针,我们可以利用它来达到我们的目的:
CMainFrame* pFrame=(CMainFrame*)(AfxGetApp()->m_pMainWnd);
通过鼠标获得子窗口指针
这里我们要用到一个不太常用的函数:ChildWindowFromPoint。他的原型如下:
CWnd* ChildWindowFromPoint(POINT point) const;
CWnd* ChildWindowFromPoint(POINT point,UINT nFlags) const;
这个函数用于确定包含指定点的子窗口,如果指定点在客户区之外,函数返回NULL;如果指定点在客户区内,但是不属于任何一个子窗口,函数返回该CWnd 的指针;如果有多个子窗口包含指定点,则返回第一个子窗口的指针。不过,这里还要注意的是:该函数返回的是一个伪窗口指针,不能将它保存起来供以后使用。
忽略任何子窗口略不可见子窗口略禁止的子窗口
在何时何地,你都可以通过以下方法精确的得到任何一个对象 (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();一个视只能有一个文
    档。\
  16. 在App中获得MainFrame指针
    CWinApp 中的 m_pMainWnd变量就是MainFrame的指针
    也可以: CMainFrame *pMain =(CMainFrame *)AfxGetMainWnd();\
  17. 在View中获得MainFrame指针 CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;\
  18. 获得View(已建立)指针 CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;
    CyouView *pView=(CyouView *)pMain->GetActiveView();\
  19. 获得当前文档指针 CDocument * pCurrentDoc =(CFrameWnd *)m_pMainWnd->GetActiveDocument();\
  20. 获得状态栏与工具栏指针 CStatusBar * pStatusBar=(CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);
    CToolBar * pToolBar=(CtoolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);\
  21. 如果框架中加入工具栏和状态栏变量还可以这样
    (CMainFrame *)GetParent()->m_wndToolBar;
    (CMainFrame *)GetParent()->m_wndStatusBar;\
  22. 在Mainframe获得菜单指针 CMenu *pMenu=m_pMainWnd->GetMenu();\
  23. 在任何类中获得应用程序类
    用MFC全局函数AfxGetApp()获得。\
  24. 从文档类取得视图类的指针
    我是从学到的,
    从文档获得视图类指针目的一般为了控制同一文档的多个视图的定位问题,我的体会
    特别是文字处理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.rn “);
    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));
    对于单文档中也可以加入多个文档模板,但是一般的开发就使用MDI方式开发
    多文档模板,其方法与上述视图的获取方法很接近,这里稍做解释,如果不清楚,
    请查阅MSDN,(以下四个内容(11、12、13、14)来源:
    http://sanjianxia.myrice.com.sixxs.org/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项中可以得到。\

Java Socket网络编程初级入门(转载)

Java Socket网络编程初级入门(转载)

转自:http://www.wang48.com/jishubaodianview/?jsd\_id=4902\
(转到自己博客,省的到处去翻)
 
事实上网络编程简单的理解就是两台计算机相互通讯数据而已,对于程序员而言,去掌握一种编程接口并使用一种编程模型相对就会显得简单的多了,Java SDK提供一些相对简单的Api来完成这些工作。Socket就是其中之一,对于Java而言,这些Api存在与java.net 这个包里面,因此只要导入这个包就可以准备网络编程了。
网络编程的基本模型就是客户机到服务器模型,简单的说就是两个进程之间相互通讯,然后其中一个必须提供一个固定的位置,而另一个则只需要知道这个固定的位置。并去建立两者之间的联系,然后完成数据的通讯就可以了,这里提供固定位置的通常称为服务器,而建立联系的通常叫做客户端,基于这个简单的模型,就可以进入网络编程啦。
Java对这个模型的支持有很多种Api,而这里我只想介绍有关Socket的编程接口,对于Java而言已经简化了Socket的编程接口。首先我们来讨论有关提供固定位置的服务方是如何建立的。Java提供了ServerSocket来对其进行支持.事实上当你创建该类的一个实力对象并提供一个端口资源你就建立了一个固定位置可以让其他计算机来访问你,ServerSocket server=new ServerSocket(6789);这里稍微要注意的是端口的分配必须是唯一的。因为端口是为了唯一标识每台计算机唯一服务的,另外端口号是从 0~65535之间的,前1024个端口已经被Tcp/Ip 作为保留端口,因此你所分配的端口只能是1024个之后的。好了,我们有了固定位置.现在所需要的就是一根连接线了.该连接线由客户方首先提出要求。因此 Java同样提供了一个Socket对象来对其进行支持,只要客户方创建一个Socket的实例对象进行支持就可以了。Socket client
=new Socket(InetAddress.getLocalHost(),5678);客户机必须知道有关服务器的IP地址,对于着一点Java也提供了一个相关的类InetAddress 该对象的实例必须通过它的静态方法来提供,它的静态方法主要提供了得到本机IP 和通过名字或IP直接得到InetAddress的方法。
上面的方法基本可以建立一条连线让两台计算机相互交流了,可是数据是如何传输的呢?事实上I/O操作总是和网络编程息息相关的。因为底层的网络是继续数据的,除非远程调用,处理问题的核心在执行上,否则数据的交互还是依赖于IO操作的,所以你也必须导入java.io这个包.java的IO操作也不复杂,它提供了针对于字节流和Unicode的读者和写者,然后也提供了一个缓冲用于数据的读写。
BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream()));
PrintWriter out=new PrintWriter(server.getOutputStream());
上面两句就是建立缓冲并把原始的字节流转变为 Unicode可以操作,而原始的字节流来源于Socket的两个方法,getInputStream()和getOutputStream()方,分别用来得到输入和输出,那么现在有了基本的模型和基本的操作工具,我们可以做一个简单的Socket例程了.
服务方:
import java.io.*;
import java.net.*;
public class MyServer {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(5678);
Socket client=server.accept();
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out=new PrintWriter(client.getOutputStream());
while(true){
String str=in.readLine();
System.out.println(str);
out.println(“has receive….”);
out.flush();
if(str.equals(“end”))
break;
}
client.close();
}
}
这个程序的主要目的在于服务器不断接收客户机所写入的信息只到,客户机发送”End”字符串就退出程序,并且服务器也会做出”Receive”为回应,告知客户机已接收到消息。
客户机代码:
import java.net.*;
import java.io.*;
public class Client{
static Socket server;
public static void main(String[] args)throws Exception{
server=new Socket(InetAddress.getLocalHost(),5678);
BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream()));
PrintWriter out=new PrintWriter(server.getOutputStream());
BufferedReader wt=new BufferedReader(new InputStreamReader(System.in));
while(true){
String str=wt.readLine();
out.println(str);
out.flush();
if(str.equals(“end”)){
break;
}
System.out.println(in.readLine());
}
server.close();
}
}
客户机代码则是接受客户键盘输入,并把该信息输出,然后输出”End”用来做退出标识。
这个程序只是简单的两台计算机之间的通讯,如果是多个客户同时访问一个服务器呢?你可以试着再运行一个客户端,结果是会抛出异常的。那么多个客户端如何实现呢?
其实,简单的分析一下,就可以看出客户和服务通讯的主要通道就是Socket本身,而服务器通过accept方法就是同意和客户建立通讯.这样当客户建立Socket的同时。服务器也会使用这一根连线来先后通讯,那么既然如此只要我们存在多条连线就可以了。那么我们的程序可以变为如下:
服务器:
import java.io.*;
import java.net.*;
public class MyServer {
public static void main(String[] args) throws IOException{
ServerSocket server=new ServerSocket(5678);
while(true){
Socket client=server.accept();
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out=new PrintWriter(client.getOutputStream());
while(true){
String str=in.readLine();
System.out.println(str);
out.println(“has receive….”);
out.flush();
if(str.equals(“end”))
break;
}
client.close();
}
}
}
这里仅仅只是加了一个外层的While循环,这个循环的目的就是当一个客户进来就为它分配一个Socket直到这个客户完成一次和服务器的交互,这里也就是接受到客户的”End”消息.那么现在就实现了多客户之间的交互了。但是.问题又来了,这样做虽然解决了多客户,可是是排队执行的。也就是说当一个客户和服务器完成一次通讯之后下一个客户才可以进来和服务器交互,无法做到同时服务,那么要如何才能同时达到既能相互之间交流又能同时交流呢?很显然这是一个并行执行的问题了。所以线程是最好的解决方案。
那么下面的问题是如何使用线程.首先要做的事情是创建线程并使得其可以和网络连线取得联系。然后由线程来执行刚才的操作,要创建线程要么直接继承Thread要么实现Runnable接口,要建立和 Socket的联系只要传递引用就可以了.而要执行线程就必须重写run方法,而run方法所做的事情就是刚才单线程版本main所做的事情,因此我们的程序变成了这样:
import java.net.*;
import java.io.*;
public class MultiUser extends Thread{
private Socket client;
public MultiUser(Socket c){
this.client=c;
}
public void run(){
try{
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out=new PrintWriter(client.getOutputStream());
//Mutil User but can’t parallel
while(true){
String str=in.readLine();
System.out.println(str);
out.println(“has receive….”);
out.flush();
if(str.equals(“end”))
break;
}
client.close();
}catch(IOException ex){
}finally{
}
}
public static void main(String[] args)throws IOException{
ServerSocket server=new ServerSocket(5678);
while(true){
//transfer location change Single User or Multi User
MultiUser mu=new MultiUser(server.accept());
mu.start();
}
}
}
我的类直接从 Thread类继承了下来.并且通过构造函数传递引用和客户Socket建立了联系,这样每个线程就有了。一个通讯管道.同样我们可以填写run方法,把之前的操作交给线程来完成,这样多客户并行的Socket就建立起来了。

Yahoo!团队实践分享:网站性能优化的35条黄金守则

Yahoo!团队实践分享:网站性能优化的35条黄金守则

Yahoo!的 Exceptional Performance团队为改善 Web性能带来最佳实践。他们为此进行了一系列的实验、开发了各种工具、写了大量的文 章和博客并在各种会议上参与探讨。最佳实践的核心就是旨在提高网站性能。

原文地址:http://developer.yahoo.com/performance/rules.html

中文转载地址:http://blog.csdn.net/alex86gbk/archive/2009/08/13/4438506.aspx

  Excetional Performance 团队总结出了一系列可以提高网站速度的方法。可以分为 7大类 34条。

    包括内容 、服务器 、 CSS 、 JavaScript 、Cookie 、图片 、移动应用 ,七部分。

其中内容部分一共十条建议:

一、内容部分

  • 尽量减少 HTTP请求
  • 减少 DNS查找
  • 避免跳转
  • 缓存 Ajxa
  • 推迟加载
  • 提前加载
  • 减少 DOM元素数量
  • 用域名划分页面内容
  • 使 frame数量最少
  • 避免 404错误

1、尽量减少 HTTP请求次数

终端用户响应的时间中,有 80%用于下载各项内容。这部分时间包括下载页面中的图像、样式表、脚本、 Flash等。通过减少页面中的元素可以减少 HTTP请求的次数。这是提高网页速度的关键步骤。

  减少页面组件的方法其实就是简化页面设计。那么有没有一种方法既能保持页面内容的丰富性又能达到加快响应时间的目的呢?这里有几条减少HTTP请求次数同时又可能保持页面内容丰富的技术。

合并文件是通过把所有的脚本放到一个文件中来减少 HTTP请求的方法,如可以简单地把所有的 CSS文件都放入一个样式表中。当脚本或者样式表在不同页面中使用时需要做不同的修 改,这可能会相对麻烦点,但即便如此也要把这个方法作为改善页面性能的重要一步。

CSS Sprites是减少图像请求的有效方法。把所有的背景图像都放到一个图片文件中,然后通过 CSS的 background-image和 background-position属性来显示图片的不同部分;

图片地图是把多张图片整合到一张图片中。虽然文件的总体大小不会改变,但是可 以减少 HTTP请求次数。图片地图只有在图片的所有组成部分在页面中是紧挨在一起的时候才能 使用,如导航栏。确定图片的坐标和可能会比较繁琐且容易出错,同时使用图片地图导航也不具有可读性,因此不推荐这种方法;

内联图像是使用 data:URL scheme的方法把图像数据加载页面中。这可能会增加页面的大 小。把内联图像放到样式表(可缓存)中可以减少 HTTP请求同时又避免增加页面文件的大小。但是内联图像现在还没有得到主流浏览器的 支持。

  减少页面的 HTTP请求次数是你首先要做的一步。这是改进首次访问用户等待时间的最重要的方法。 如同 Tenni Theurer的他的博客 Browser Cahe Usage – Exposed!中所说, HTTP请求在无缓存情况下占去了 40%到 60%的响应时间。让那些初次访问你网站的人获得更加快速的体验吧!

2、减少 DNS查找次数

  域名系统( DNS)提供了域名和 IP的对应关系,就像电话本中人名和他们的电话号码的关系一样。当你在浏览器地址栏中 输入 www.yahoo.com 时, DNS解析服务器就会返回这个域名对应的 IP地址。 DNS解析的过程同样也是需要时间的。一般情况下返回给定域名对应的 IP地址会花费 20到 120毫秒的时间。而且在这个过程中浏览器什么都不会做直到 DNS查找完毕。

   缓存 DNS查找可以改善页面性能。这种缓存需要一个特定的缓存服务器,这种服务器一般属于用户的 ISP提供商或者本地局域网控制,但是它同样会在用户使用的计算机上产生缓存。 DNS信息会保留在操作系统的 DNS缓存中(微软 Windows系统中 DNS Client Service)。大多数浏览器有独立于操作系统以外的自己的缓存。由于浏览器有自己的缓存记录,因此在一次请求中它不会受到操作系统的影响。

  Internet Explorer 默认情况下对 DNS查找记录的缓存时间为 30分钟,它在注册表中的键值为 DnsCacheTimeout。 Firefox对 DNS的查找记录缓存时间为 1分钟,它在配置文件中的选项为 network.dnsCacheExpiration( Fasterfox把这个选项改为了 1小时)。

  当客户端中的 DNS缓存都为空时(浏览器和操作系统都为空), DNS查找的次数和页面中主机名的数量相同。这其中包括页面中 URL、图片、脚本文件、样式表、Flash对象等包含的主机名。减少主机名的数量可以减少DNS查找次数。

  减少主机名的数量还可以减少页面中并行下载的数量。减少 DNS查找次数可以节省响应时间,但是减少并行下载却会增加响应时间。我的指导原则是 把这些页面中的内容分割成至少两部分但不超过四部分。这种结果就是在减少 DNS查找次数和保持较高程度并行下载两者之间的权衡了。

3、避免跳转

跳转是使用 301和 302代码实现的。下面是一个响应代码为 301的 HTTP头:

      HTTP/1.1 301 Moved Permanently

      Location: http://example.com/newuri

      Content-Type: text/html

  浏览器会把用户指向到 Location中指定的 URL。头文件中的所有信息在一次跳转中都是必需的,内容部分可以为空。不管他们的名 称, 301和 302响应都不会被缓存除非增加一个额外的头选项,如 Expires或者 Cache-Control来指定它缓存。 元素的刷新标签和JavaScript也可以实现 URL的跳转,但是如果你必须要跳转的时候,最好的方法就是使用标准的 3XXHTTP状态代码,这主要是为了确保“后退”按钮可以正确地使用。

  但是要记住跳转会降低用户体验。在用户和 HTML文档中间增加一个跳转,会拖延页面中所有元素的显示,因为在 HTML文件被加载前任何文件(图像、 Flash等)都不会被下载。

  有一种经常被网页开发者忽略却往往十分浪费响应时间的跳转现象。 这种现象发生在当 URL本该有斜杠( /)却被忽略掉时。例如,当我们要访问 http://astrology.yahoo.com/astrology 时,实际上返回的是一个包含 301代码的跳转,它指向的是 http://astrology.yahoo.com/astrology/  (注意末尾的斜杠)。在 Apache服务器中可以使用 Alias 或者 mod_rewrite或者 the DirectorySlash来避免。

  连接新网站和旧网站是跳转功能经常被用到的另一种情况。这种情况 下往往要连接网站的不同内容然后根据用户的不同类型(如浏览器类型、用户账号所属类型)来进行跳转。使用跳转来实现两个网站的切换十分简单,需要的代码量 也不多。尽管使用这种方法对于开发者来说可以降低复杂程度,但是它同样降低用户体验。一个可替代方法就是如果两者在同一台服务器上时使用 Alias和 mod_rewrite和实现。如果是因为域名的不同而采用跳转,那么可以通过使用 Alias或者 mod_rewirte建立 CNAME(保存一个域名和另外一个域名之间关系的DNS记录)来替代。

4、可缓存的 AJAX

  Ajax 经常被提及的一个好处就是由于其从后台服务器传输信息 的异步性而为用户带来的反馈的即时性。但是,使用 Ajax并不能保证用户不会在等待异步的 JavaScript和 XML响应上花费时间。在很多应用中,用户是否需要等待响应取决于 Ajax如何来使用。例如,在一个基于 Web的 Email客户端中,用户必须等待 Ajax返回符合他们条件的邮件查询结果。记住一点,“异步”并不异味着“即时”,这 很重要。

  为了提高性能,优化 Ajax响应是很重要的。提高 Ajxa性能的措施中最重要的方法就是使响应具有可缓存性,具体的讨论可以查看 Add an Expires or a Cache-Control Header。 其它的几条规则也同样适用于Ajax:

    Gizp 压缩文件

    减少 DNS查找次数

    精简 JavaScript

    避免跳转

    配置 ETags

  让我们来看一个例子:一个 Web2.0的 Email客户端会使用 Ajax来自动完成对用户地址薄的下载。如果用户在上次使用过 Email web应用程序后没有对地址薄作任何的修改,而且 Ajax响应通过 Expire或者 Cacke-Control头来实现缓存,那么就可以直接从上一次的缓存中读取地址薄 了。必须告知浏览器是使用缓存中的地址薄还是发送一个新的请求。这可以通过为读取地址薄的 Ajax URL增加一个含有上次编辑时间的时间戳来实现,例如, &t=11900241612等。如果地址薄在上次下载后没有被编辑过,时间 戳就不变,则从浏览器的缓存中加载从而减少了一次 HTTP请求过程。如果用户修改过地址薄,时间戳就会用来确定新的 URL和缓存响应并不匹配,浏览器就会重要请求更新地址薄。

  即使你的 Ajxa响应是动态生成的,哪怕它只适用于一个用户,那么它也应该被缓存起来。这样做 可以使你的 Web2.0应用程序更加快捷。

5、推迟加载内容

  你可以仔细看一下你的网页,问问自己“哪些内容是页面呈现时 所必需首先加载的?哪些内容和结构可以稍后再加载?

  把整个过程按照 onload事件分隔成两部分, JavaScript是一个理想的选择。例如,如果你有用于实现拖放和动画的 JavaScript,那么它就以等待稍后加载,因为页面上的拖放元素是在初始化呈现 之后才发生的。其它的例如隐藏部分的内容(用户操作之后才显现的内容)和处于折叠部分的图像也可以推迟加载

  工具可以节省你的工作量: YUI Image Loader可以帮你推迟加载折叠部分的图片, YUI Get utility是包含 JS和 CSS的便捷方法。比如你可以打开 Firebug的 Net选项卡看一下 Yahoo的首页。

  当性能目标和其它网站开发实践一致时就会相得益彰。这种情况 下,通过程序提高网站性能的方法告诉我们,在支持 JavaScript的情况下,可以先去除用户体验,不过这要保证你的网站在没有 JavaScript也可以正常运行。在确定页面运行正常后,再加载脚本来实现如拖放和动画等更加花哨的效果。

6、预加载

  预加载和后加载看起来似乎恰恰相反,但实际上预加载是为了实 现另外一种目标。预加载是在浏览器空闲时请求将来可能会用到的页面内容(如图像、样式表和脚本)。使用这种方法,当用户要访问下一个页面时,页面中的内容 大部分已经加载到缓存中了,因此可以大大改善访问速度。

下面提供了几种预加载方法:

  无条件加载:触发 onload事件时,直接加载额外的页面内容。以 Google.com为例,你可以看一下它的 spirit image图像是怎样在 onload中加载的。这个 spirit image图像在 google.com主页中是不需要的,但是却可以在搜索结果页面中用到它。

有条件加载:根据用户的操作来有根据地判断用户下面可能去往的页面并相应的预 加载页面内容。在 search.yahoo.com中你可以看到如何在你输入内容时加载额外的页面内容。

  有预期的加载:载入重新设计过的页面时使用预加载。这种情况经常出现在页面经过重新设计后用户抱怨“新的页面看起来很酷,但是却比以前慢”。问题可能出在 用户对于你的旧站点建立了完整的缓存,而对于新站点却没有任何缓存内容。因此你可以在访问新站之前就加载一部内容来避免这种结果的出现。在你的旧站中利用 浏览器的空余时间加载新站中用到的图像的和脚本来提高访问速度。

7、减少 DOM元素数量

  一个复杂的页面意味着需要下载更多数据,同时也意味着 JavaScript遍历 DOM的效率越慢。比如当你增加一个事件句柄时在 500和 5000个 DOM元素中循环效果肯定是不一样的。

  大量的 DOM元素的存在意味着页面中有可以不用移除内容只需要替换元素标签就可以精简的部分。你在页面布局中使用表格了吗?你有没有仅仅为了布局而引入更多的

元素呢?也许会存在一个适合或者在语意是更贴切的标签可以供你使用。

  YUI CSS utilities 可以给你的布局带来巨大帮助: grids.css可以帮你实现整体布局, font.css和 reset.css可以帮助你移除浏览器默认格式。它提供了一个重新审视你页面中标签 的机会,比如只有在语意上有意义时才使用

,而不是因为它具有换行效果才使用它。

  DOM 元素数量很容易计算出来,只需要在 Firebug的控制台内输入:

document.getElementsByTagName(‘*’).length

  那么多少个 DOM元素算是多呢?这可以对照有很好标记使用的类似页面。比如 Yahoo!主页是一个内容非常多的页面,但是它只使用了 700个元素( HTML标签)。

8、根据域名划分页面内容

  把页面内容划分成若干部分可以使你最大限度地实现平行下载。由于 DNS查找带来的影响你首先要确保你使用的域名数量在 2个到 4个之间。例如,你可以把用到的 HTML内容和动态内容放在 http://www.example.org/ 上,而把页面各种组件(图片、脚本、 CSS)分别存放在 statics1.example.org和 statics.example.org上。

你可在 Tenni Theurer和 Patty Chi合写的文章 Maximizing Parallel Downloads in the Carpool Lane找到更多相关信息。

9、使 iframe的数量最小

  ifrmae 元素可以在父文档中插入一个新的 HTML文档。了解 iframe的工作理然后才能更加有效地使用它,这一点很重要。