??xml version="1.0" encoding="utf-8" standalone="yes"?>色综合久久中文字幕无码,久久AV无码精品人妻糸列,久久综合九色综合久99http://www.shnenglu.com/microli/articles/13664.html铁观?/dc:creator>铁观?/author>Sat, 14 Oct 2006 02:44:00 GMThttp://www.shnenglu.com/microli/articles/13664.htmlIntroduction

The ZSplitterDlg and ZSplitter classes help you to add splitters to your dialog, property sheet or any other window. It splits your controls and makes them movable and resizeable. I think this way is better than "auto size" contol: it adds a "docking" opportunity. Moreover, one more control added that add "auto size" option. Finally, you can integrate the ZSplitterDlg with a resizable dialog (for example CResizableDialog by Paolo Messina).

Note that you shouldn't add anything to your resources and shouldn't describe the relations between controls. Just make the corresponding size and position of your controls and use the functions:

				void addControls(int count, bool connectVertical, ...);
void addControl(int id);

Demo project shows using these automatically added controls in CDialog, CPropertyPage, CView and CFormView classes.

Sample Image

Using the class

The simplest way is to use the ZSplitterDlgImpl template. You should change:

  • The parent of your dialog ot view class,
  • the constructor implementation,
  • the second parameter in BEGIN_MESSAGE_MAP macros, and
  • the "on init" function of your window.
				// in header
				class CTestDlg1 : public ZSplitterDlgImpl<CPropertyPage>

// in source
CTestDlg1::CTestDlg1() : /*...*/ ZSplitterDlgImpl<CPropertyPage>(CTestDlg1::IDD) {}

BEGIN_MESSAGE_MAP(CTestDlg1, ZSplitterDlgImpl<CPropertyPage>)
	//	...
END_MESSAGE_MAP()

BOOL CTestDlg1::OnInitDialog() 
{
	// ... and use addControl(s) function here
	init();
	// ...
}

The ZSplitterDlgImpl template has a second parameter (ZSplitter2 by default). ZSplitter2 is the implementation of a spliter control. It has a virtual function OnPaint() - and you can change it's realisation to have different view of your control (see CMyView1 class in demo project).

The ZSplitterDlgImpl template helps you to implement splitter controls but you can use its base ZSplitterDlg class (look for CTestDlg2 class) in demo project.

I remade a little CResizableDialog with the permission of the author and you can use it with my splitters: use the ZSplitterDlgResizable class for this job. (look for CDemoDlg class) in the demo project.

resizable sample

This is a sample of your dialog in resource editor:

in vc++ editor

And user can change it in such way in runtime.

after user manipulations

You should use the addControls or addControl functions to add one control to the "splitter set" or a group of controls: they will move together. This is an example which you seen above

  addControls(2,false,IDC_LIST6,IDC_LIST7);
  addControls(2,true,IDC_LIST1,IDC_LIST8);
  addControl(IDC_LIST9);
  addControl(IDC_LIST2);
  addControl(IDC_LIST3);
  addControl(IDC_LIST4);
  addControl(IDC_LIST5);

Moreover you can manually add a ZSplitter class (the most common splitter controls) to a page. Look at the images and in the CTestDlg3 class of the demo project for details.

before moving after moving

To Do list

I'd like to make the look (color, size, effects) of the splitter more presentable. So I want to get comments from you. First of all: is this technique useful to you?

Note

Make sure to check out the my web site which is more likely to have updates and betas:
http://www.zmike.net

About Mike Melnikov


Mike has been programming in C/C++ for 11 years and Visual C++/MFC for 4 years. His background includes pure and applied mathematics, engineering and physics, and he is currently based in Moscow, Russia.

Click here to view Mike Melnikov's online profile.



]]>
CSplitterWnd in a Dialog based Applicationhttp://www.shnenglu.com/microli/articles/13663.html铁观?/dc:creator>铁观?/author>Sat, 14 Oct 2006 02:42:00 GMThttp://www.shnenglu.com/microli/articles/13663.html 

Had this problem before. I guess there are some more interested in a solution.

It seems CSplitterWnd is designed to be used in document/view-based applications only.
But by overriding some virtual methods in a derived class, you can make splitter windows based on CSplitterWnd be used in dialog based application, ActiveX-Controls using MFC:

All virtual methods that call GetParentFrame() in its implementation have to be overridden.
I have done this by using existing code except
- that I replaced the call to GetParentFrame() by a call to GetParent().
- all references or pointers to CFrameWnd were changed to references or pointers to CWnd.

I derived a class CxSplitterWnd from the class CSplitterWnd and proceeded as stated above.
Then I used this class in a dialog based application in the same way as any other CWnd derived class.
For example:

class CSampleDialog : public CDialog
{
	...
	CxSplitterWnd m_wndSplitter;
	....
}

BOOL CSampleDlg::OnInitDialog()
{
...
	// TODO: Add extra initialization here
	m_wndSplitter.CreateStatic(this, 1, 2);
	m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CSampleView), CSize(50,0), NULL);
	m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CSampleView), CSize(0,0), NULL);

	CRect rect = ...;
	m_wndSplitter.MoveWindow(&rect);
	...
}

The sample attached is a dialog based application and demonstrates the use of CxSplitterWnd. It does
nothing useful.

This is the new class declaration:

// SplitWnd.h : implementation file// class CxSplitterWnd : public CSplitterWnd
{
	// Constructionpublic:
	CxSplitterWnd() {};
	virtual ~CxSplitterWnd() {};

	// Operationspublic:
	// Overrides// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CxSplitterWnd)//}}AFX_VIRTUAL // Implementationpublic:
	// These are the methods to be overriddenvirtualvoid StartTracking(int ht);
	virtual CWnd* GetActivePane(int* pRow = NULL, int* pCol = NULL);
	virtualvoid SetActivePane( int row, int col, CWnd* pWnd = NULL );
	virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
	virtual BOOL OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult );
	virtual BOOL OnWndMsg( UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult );

	// Generated message map functionsprotected:
	//{{AFX_MSG(CxSplitterWnd)// NOTE - the ClassWizard will add and remove member functions here.//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

And here the implementation file:
// SplitWnd.cpp : implementation file// #include "stdafx.h"
#include "SplitWnd.h"

#ifdef _DEBUG
#definenew DEBUG_NEW
#undef THIS_FILE
staticchar THIS_FILE[] = __FILE__;
#endif

// HitTest return values (values and spacing between values is important)// Had to adopt this because it has module scope enum HitTestValue
{
	noHit = 0,
	vSplitterBox = 1,
	hSplitterBox = 2,
	bothSplitterBox = 3, // just for keyboard
	vSplitterBar1 = 101,
	vSplitterBar15 = 115,
	hSplitterBar1 = 201,
	hSplitterBar15 = 215,
	splitterIntersection1 = 301,
	splitterIntersection225 = 525
};

/////////////////////////////////////////////////////////////////////////////// CxSplitterWnd 

BEGIN_MESSAGE_MAP(CxSplitterWnd, CSplitterWnd)
//{{AFX_MSG_MAP(CxSplitterWnd)// NOTE - the ClassWizard will add and remove mapping macros here.//}}AFX_MSG_MAP
END_MESSAGE_MAP()

CWnd* CxSplitterWnd::GetActivePane(int* pRow, int* pCol)
{
	ASSERT_VALID(this);
	CWnd* pView = GetFocus();
	// make sure the pane is a child pane of the splitterif (pView != NULL && !IsChildPane(pView, pRow, pCol))
	pView = NULL;
	return pView;
}

void CxSplitterWnd::SetActivePane( int row, int col, CWnd* pWnd)
{
	// set the focus to the pane
	CWnd* pPane = pWnd == NULL ? GetPane(row, col) : pWnd;
	pPane->SetFocus();
}

void CxSplitterWnd::StartTracking(int ht)
{
ASSERT_VALID(this);
	if (ht == noHit)
		return;
	// GetHitRect will restrict 'm_rectLimit' as appropriate
	GetInsideRect(m_rectLimit);
	if (ht >= splitterIntersection1 && ht <= splitterIntersection225)
	{
		// split two directions (two tracking rectangles)int row = (ht - splitterIntersection1) / 15;
		int col = (ht - splitterIntersection1) % 15;
		GetHitRect(row + vSplitterBar1, m_rectTracker);
		int yTrackOffset = m_ptTrackOffset.y;
		m_bTracking2 = TRUE;
		GetHitRect(col + hSplitterBar1, m_rectTracker2);
		m_ptTrackOffset.y = yTrackOffset;
	}
	elseif (ht == bothSplitterBox)
	{
		// hit on splitter boxes (for keyboard)
		GetHitRect(vSplitterBox, m_rectTracker);
		int yTrackOffset = m_ptTrackOffset.y;
		m_bTracking2 = TRUE;
		GetHitRect(hSplitterBox, m_rectTracker2);
		m_ptTrackOffset.y = yTrackOffset;
		// center it
		m_rectTracker.OffsetRect(0, m_rectLimit.Height()/2);
		m_rectTracker2.OffsetRect(m_rectLimit.Width()/2, 0);
	}
	else
	{
		// only hit one bar
		GetHitRect(ht, m_rectTracker);
	}

	// steal focus and capture
	SetCapture();
	SetFocus();
	// make sure no updates are pending
	RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);
	// set tracking state and appropriate cursor
	m_bTracking = TRUE;
	OnInvertTracker(m_rectTracker);
	if (m_bTracking2)
	OnInvertTracker(m_rectTracker2);
	m_htTrack = ht;
	SetSplitCursor(ht);
}

/////////////////////////////////////////////////////////////////////////////// CSplitterWnd command routing 
BOOL CxSplitterWnd::OnCommand(WPARAM wParam, LPARAM lParam)
{
	if (CWnd::OnCommand(wParam, lParam))
	return TRUE;
	// route commands to the splitter to the parent frame windowreturn GetParent()->SendMessage(WM_COMMAND, wParam, lParam);
}

BOOL CxSplitterWnd::OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult )
{
	if (CWnd::OnNotify(wParam, lParam, pResult))
	return TRUE;
	// route commands to the splitter to the parent frame window
	*pResult = GetParent()->SendMessage(WM_NOTIFY, wParam, lParam);
	return TRUE;
}

BOOL CxSplitterWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
	// The code line below is necessary ifusing CxSplitterWnd in a regular dll// AFX_MANAGE_STATE(AfxGetStaticModuleState()); return CWnd::OnWndMsg(message, wParam, lParam, pResult);
}


]]>
VC设计分割视图通用创徏框架http://www.shnenglu.com/microli/articles/11914.html铁观?/dc:creator>铁观?/author>Fri, 01 Sep 2006 02:08:00 GMThttp://www.shnenglu.com/microli/articles/11914.html 介?br />  目前Z分割视图的应用开发十分流行,分割视图技术是在同一个框架窗口下同时昄多个视图的一Ҏ术。运用分割视图,可以在较短时间内l用h多的信息量,从而得用L面更加的友好Q增Z软g的可操作性。本文提Z个分割视囄通用创徏框架?

目前Z分割视图的应用开发十分流行,分割视图技术是在同一个框架窗口下同时昄多个视图的一Ҏ术。运用分割视图,可以在较短时间内l用h多的信息量,从而得用L面更加的友好Q增Z软g的可操作性。本文提Z个分割视囄通用创徏框架。  

  1Q分割视囑ֈ建框?

  分割视图的创建大体上分ؓ两个步骤Q其一是创建分割窗体;然后是处理鼠标和键盘等消息?

  1) 创徏分割H体

  MFC提供分割H体cCsplitterWndQ它提供了很多对于分割窗体操作的成员函数Q每一个分割窗体都是一个CsplitterWnd的对象。本文提出的框架׃需要对定制的分割窗体进行扩充处理,所以首先从CsplitterWndl承一个子cCFixSplitterWndQ然后每个分割窗体是一个CfixSplitterWnd的对象,q样以后只需要对CfixSplitterWndq行改写后就可以增强分割H体的功能。(后面提U改写)

  创徏分割H体最重要的函数是L架类的OnCreateClient函数Q它在L架创建的时候调用,本文创Z个如下显C的分割H体Q?

VC设计分割视图通用创徏框架
  

  则可以如下实玎ͼ  

  //成员变量声明

  CFixSplitterWnd m_wndSplitterH; //用于横向切割

  CFixSplitterWnd m_wndSplitterV; //用于U向切割

  BOOL m_bCreateSplitter;  

  //分割H体的实?

  BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)

  {

  //Ҏ个主框架q行混合分割视图

  BOOL bResult=m_wndSplitterV.CreateStatic(this,1,2);

  ASSERT(bResult);

  m_wndSplitterH.CreateStatic(&m_wndSplitterV,4,1,WS_CHILD   WS_VISIBLE,m_wndSplitterV.IdFromRowCol(0,1));

//创徏各自子窗片的对应的视?

  m_wndSplitterV.CreateView(0,0,RUNTIME_CLASS(CSceneView),CSize(600,600),pContext);

  m_wndSplitterH.CreateView(0,0,RUNTIME_CLASS(CPitchView),CSize(100,100),pContext);

  m_wndSplitterH.CreateView(1,0,RUNTIME_CLASS(CYawView),CSize(100,100),pContext);

  m_wndSplitterH.CreateView(2,0,RUNTIME_CLASS(CRollView),CSize(100,100),pContext);

  m_wndSplitterH.CreateView(3,0,RUNTIME_CLASS(CControlView),CSize(100,100),pContext);

  //讄H格的初始化的大?

  m_wndSplitterV.SetRowInfo(0,IDEAL_RAWHEIGHT,0);

  m_bCreateSplitter=TRUE;

  //Ȁzsceneview使得其可以接受命令消?

  m_wndSplitterV.SetActivePane(0,0,NULL);

  return bResult;

  }

  //L架窗体大发生变化,调节相应的窗体大?

  void CMainFrame::OnSize(UINT nType, int cx, int cy)

  {

  CMDIFrameWnd::OnSize(nType, cx, cy);

  CRect rect;

  GetClientRect(rect);

  if (m_bCreateSplitter) 
      {

  m_wndSplitterV.SetColumnInfo(0,rect.Width() *3/4,10);

  m_wndSplitterV.SetColumnInfo(1,rect.Width() *1/4,10);

  m_wndSplitterH.SetRowInfo(0,rect.Height() /6,10);

  m_wndSplitterH.SetRowInfo(1,rect.Height() /6,10);

  m_wndSplitterH.SetRowInfo(2,rect.Height() /6,10);

  m_wndSplitterH.SetRowInfo(3,rect.Height()/2,10);

  }

  m_wndSplitterV.RecalcLayout();

  m_wndSplitterH.RecalcLayout();

  }

  注意m_wndSplitterH.CreateView 中的W二个参敎ͼq个参数分割窗体和相应的视囄相对应?

  通过上述的程序代码即可创建图1所C的分割H体Q那么由于这里每个分割窗体都是一个CfixSplitterWnd对象Q所以可以通过改写CfixSplitterWndcȝ虚函数或消息处理函数来完成自q定的应用实现。(注意Q如果需要对定制有特定属性的分割H体Q一定要z自己的分割窗体类而不能是MFC的CsplitterWndc)q里我们需要分割窗体不能随鼠标拖动而改变其大小Q即所有窗格的大小都是一定的Q不能在q行时刻改变。所以必dCfixSplitterWndcȝ实现中加入如下代码:  

  void CFixSplitterWnd::OnMouseMove(UINT nFlags, CPoint point)

  {

  CWnd::OnMouseMove(nFlags, point); //防止鼠标出现拖动?

  // CSplitterWnd::OnMouseMove(nFlags, point); //鼠标会在H体边界出现拖动?

  }

  xQ分割窗体已l创建完毕,下面需要在分割H体里处理消息?

  2) 分割H体处理消息

  在分割窗体里处理消息和一般的文档视图模型处理消息大致一P但它也有其特D之处。具体来?׃各个分割H体已经与具体的视图cȝ联系了,所以在需要处理各个分割窗体中的消息时Q可以直接到相应的视囄中进行处理;另外Q多视图之间的切换会D目标焦点之间的变_q样会媄响菜单中与视图有关的命o的执行。比如在?中所C的分割H体中,有一个“开始”命令必L焦点在CsceneView视图上时才能执行Q否则就应该让该命o不能执行Q即该菜单呈现灰ԌQ则实现时可以首先对鼠标q行点击试Q判断是否在CsceneView视图范围内,如果是的话就允许执行Q否则就不允许执行?

  2Q结?

  通过本文提出的分割视囑ֈ建框Ӟ可以满对视图进行复杂控制的需求,希望本文可以l大家一个启发,从而能够创建更为完的分割视图应用E序?a >


]]>
使用VC6.0实现H口的Q意分?/title><link>http://www.shnenglu.com/microli/articles/11913.html</link><dc:creator>铁观?/dc:creator><author>铁观?/author><pubDate>Fri, 01 Sep 2006 01:56:00 GMT</pubDate><guid>http://www.shnenglu.com/microli/articles/11913.html</guid><description><![CDATA[ <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td width="40" height="74"> </td> <td valign="top" width="*" height="74"> <form name="form2" action="/SYS/script/find.asp" method="post"> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td> <span id="docinfo">[ <font color="#009900">原创文档</font> 本文适合中读?已阅读n?]</span> </td> <td align="right"> <input class="rect" maxlength="20" size="10" name="keyword" /> <select class="rect" name="gclsid"> <option value="100" selected="">文档</option> <option value="200">代码</option> <option value="400">工具</option> </select> <input type="image" height="15" width="21" src="http://www.vckbase.com/document/image/go.gif" align="absMiddle" border="0" name="imageField" /> </td> </tr> </tbody> </table> </form> <p align="center"> <span id="h9rl9f9" class="big"> <b> <font color="#006633">使用VC6.0实现H口的Q意分?/font> <br /> </b>南京邮政局计算Z?张中?/span> </p> <div align="center"> <table class="big" height="46" cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td> <p> <b>一、关于CSplitterWndc?/b> <br />我们在用CuteFtp或者NetAnt{工L时候,一般都会被其复杂的界面所吸引Q在q些界面中窗口被分割q的区域Q真正做CH口的Q意分剌Ӏ?那么我们自己如何创徏cM的界面,也实现窗口的L的分割呢 Q在VC6.0中这需要用到CSplitterWndcRCSplitterWnd看上d是一U特D的框架H口Q每个窗口都被相同的或者不同的视图所填充。当H口被切分后用户可以使用鼠标Ud切分条来调整H口的相对尺寸。虽然VC6.0支持从AppWizard中创建分割窗口,但是自动加入的分割条L不能让我们满意,因此我们q是通过手工增加代码来熟悉这个类?<br />CSplitterWnd的构造函C要包括下面三个?<br /></p> <pre>BOOL Create(CWnd* pParentWnd,int nMaxRows,int nMaxCols,SIZE sizeMin,CCreateContext* pContext,DWORD dwStyle,UINT nID);</pre>功能描述Q该函数用来创徏动态切分窗口?参数含义QpParentWnd 切分H口的父框架H口?nMaxRows,nMaxCols是创建的最大的列数和行数?sizeMin是窗格的现实大小?pContext 大多数情况下传给父窗口?nID是字H口的ID? <pre>BOOL CreateStatic(CWnd* pParentWnd,int nRows,int nCols,DWORD dwStyle,UINT nID) </pre>功能描述Q用来创建切分窗口?参数含义同上?<pre>BOOL CreateView (int row,int col,CruntimeClass* pViewClass,SIZE sizeinit,CcreateContext* pContext);</pre>功能描述Qؓ静态切分的H口的网格填充视图。在视图于切分H口联系在一L时候必 d切分窗口创建好?<br />参数含义Q同上?br />从CSplitterWnd源程序可以看Z是使用动态创建Createq是使用静态创建CreateStaticQ在函数中都调用了一个保护函数CreateCommonQ从下面的CreateCommon函数中的关键代码可以看出创徏CSplitterWnd的实质是创徏了一pd的MDI子窗口?<br /><pre>DWORD dwCreateStyle = dwStyle & ~(WS_HSCROLL|WS_VSCROLL); if (afxData.bWin4) dwCreateStyle &= ~WS_BORDER; //create with the same wnd-class as MDI-Frame (no erase bkgnd) if (!CreateEx(0, _afxWndMDIFrame, NULL, dwCreateStyle, 0, 0, 0, 0,pParentWnd->m_hWnd, (HMENU)nID, NULL)) return FALSE; // create invisible </pre><br /><b>二、创建嵌套分割窗?/b><br /><b>2.1创徏动态分割窗?/b><br />动态分割窗口用CreateҎ。下面的代码创?x2的窗根{?<br /><pre>m_wndSplitter.Create(this,2,2,CSize(100,100),pContext);</pre><br />但是动态创建的分割H口的窗格数目不能超q?x2Q而且对于所有的H格Q都必须׃n同一个视图,所受的限制也比较多Q因此我们不动态创Z为重炏V我们的主要_֊攑֜静态分割窗口的创徏上?<br /><b>2.2创徏静态分割窗?/b><br />与动态创建相比,静态创建的代码要简单许多,而且可以最多创?6x16的窗根{不同的H格我们可以使用CreateView填充不同的视图?<br />在这里我们将创徏CuteFtp的窗口分剌ӀCuteFtp的分割情况如下: <div align="center"><table height="223" cellspacing="1" cellpadding="0" width="446" bgcolor="#666666" border="0"><tbody><tr bgcolor="#eeeeee"><td colspan="2" height="46"><div align="center"><font face="Arial, Helvetica, sans-serif" size="2">CCuteFTPView</font></div></td></tr><tr bgcolor="#eeeeee"><td height="123"><div align="center"><font face="Arial, Helvetica, sans-serif" size="2">CView2</font></div></td><td height="123"><div align="center"><font face="Arial, Helvetica, sans-serif" size="2">CView3</font></div></td></tr><tr bgcolor="#eeeeee"><td colspan="2" height="44"><div align="center"><font face="Arial, Helvetica, sans-serif" size="2">CView4</font></div></td></tr></tbody></table></div><p>创徏步骤Q?<br />?在创Z前我们必d用AppWizard生成单文档CuteFTPQ生成的视类?CCuteFTPView.同时在增加三个视cL者从视类l承而来的派生类CView2,CView3 CView4. <br />?<b>增加成员Q?/b><br />在Cmainfrm.h中我们将增加下面的代码: <br /></p><pre>CSplitterWnd wndSplitter1; CSplitterWnd wndSplitter2;</pre>?<b>重蝲CMainFrame::OnCreateClient()函数Q?/b><pre>BOOL CMainFrame::OnCreateClient( LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext) { //创徏一个静态分栏窗口,分ؓ三行一? if(m_wndSplitter1.CreateStatic(this,3,1)==NULL) return FALSE; //CCuteFTPViewq接??列窗g m_wndSplitter1.CreateView(0,0,RUNTIME_CLASS(CCuteFTPView),CSize(100,100), pContext); m_wndSplitter1.CreateView(2,0,RUNTIME_CLASS(CView4),CSize(100,100),pContext); //CView4q接??? if(m_wndSplitter2.CreateStatic(&m_wndSplitter,1,2,WS_CHILD|WS_VISIBLE, m_wndSplitter.IdFromRowCol(1, 0))==NULL) return FALSE; //第1?列再分开1?? //CView2c连接到W二个分栏对象的0?? m_wndSplitter2.CreateView(0,0,RUNTIME_CLASS(CView2),CSize(400,300),pContext); //CView3c连接到W二个分栏对象的0?? m_wndSplitter2.CreateView(0,1,RUNTIME_CLASS(CView3),CSize(400,300),pContext); return TRUE; } </pre><b>2.3实现各个分割区域的通信</b><br />?b>有文档相q的视图之间的通信<br /></b>由AppWizard生成的CCuteFTPView是与文档相连的,同时我们也让CView2与文档相q,因此我们需要修改CCuteFTPApp的InitInstance()函数Q我们将增加下面的部分?br /><pre>AddDocTemplate (new CMultiDocTemplate(IDR_VIEW2TYPE, RUNTIME_CLASS(CMainDoc), RUNTIME_CLASS(CMDIChildWnd), RUNTIME_CLASS(CView2))); </pre>我们现在来实现CCuteFTPView与CView2之间的通信。由于跟文档cȝq的视图c?是不能安全的与除文档cM外的其余的视囄通信的。因此我们只能让他们都与文档 c通信。在文档中我们设|相应的指针以用来获的各个视图。我们重?CCuteFTPView::OnOpenDocument()函数Q?<br /><pre>CCuteFTPView* pCuteFTPView;<br />CView2* pView2; POSITION pos; CView* pView; while(pos!=NULL) { pView=GetNextView(pos); if(pView->IsKindOf(RUNTIME_CLASS(CCuteFTPView))==NULL) pCuteFTPView=(CCuteFTPView*)pView; else(pView->IsKindOf(RUNTIME_CLASS(CCuteFTPView))==NULL) pView2=(CView2*)pView; } </pre>q样我们在文档类中就L了跟它相q的所有的视图的指针?br />如果需要在 CCuteFTPView中调用CView2中的一个方法DoIt()则代码如下: <br /><pre>CCuteFTPDoc* pDoc=GetDocument();<br />CView2* pView2=pDoc->pView3;<br />pView3.DoIt(); </pre><br />?b>无文档视图与文档兌视图之间的通信<br /></b>CView3和CView4都是不与文档相关联的。我们现在实现CView3与CView2的通信.正如前面所_CView2只能安全的与CCuteFTPDoc通信Q因此,CView3如果需要跟CView2通信Q也必须借助于文档类。因此程序的关键是如何在CView3中获得文档的指针。视囄中没有这LcL员可以用来直接访问文档类。但是我们知道在ȝ口类MainFrame中我们可以获得程序的LH口cȝ指针。因此我们只要获得程序主H口了的指针Q就可以解决问题了。代码实现在CView3中访问CView2中的DoIt()Ҏ?br /><br />CView3中的代码如下Q?<pre>CMainFrame* MainFrame=(CMainFrame*)this->GetParent()->GetParent(); CCuteFTPDoc* Doc=(CCuteFTPDoc*)MainFrame->GetActiveDocument(); if(Doc!=NULL) Doc->DoIt(); CCuteFTPDoc中的相应的处理函数DoIt()代码如下Q? CView2* pView2; POSITION pos; CView* pView; while(pos!=NULL) { pView=GetNextView(pos); if(pView->IsKindOf(RUNTIME_CLASS(CView2))==NULL) pView2=(CView2*)pView; } pView2->DoIt(); </pre>?b>无文档关联视图之间的通信<br /></b>CView3和CView4都是不跟文档相连的,如何实现他们之间的通信呢?正如我们在上面所说的那样Q由于在L架中我们可以讉KL的视图,因此我们的主要Q 务还是在E序中获得主框架的指针。在CView3中访问CView4中的ҎDoIt()?<br /><pre>CMainFrame* MainFrame=(CMainFrame*)this->GetParent()->GetParent(); CView4* View4=(CView4*)MainFrame->m_wndSplitter1.GetPane(2,0); View4->DoIt(); </pre><br />到现在我们已l实CCuteFTP的主H口的框架ƈ且能够实C们之间相互通信的框架?同样的我们可以实现其他的一些流行界面例如NetAntsQFoxmail的分剌Ӏ?<br /><br /><b>三、关于对话框的分?/b><br />到目前ؓ止,只有Z文档/视图的程序才能用CSplitterWndQ而基于对话框的应用程序却不支持CSplitterWnd,但是如果我们在承类中重载一些虚拟方法,也能使CSplitterWnd 在对话框E序中用。从MFC的源E序WinSplit.cpp中可以看出,Z获得父窗口的地方E序都调用了虚拟ҎGetParentFrame(),因此如果在对话框中用,我们必须它改ؓGetParent();因此我们CSplitterWnd的下面几个方法重载?br /><pre>virtual void StartTracking(int ht); virtual CWnd* GetActivePane(int* pRow = NULL, int* pCol = NULL); virtual void SetActivePane( int row, int col, CWnd* pWnd = NULL ); virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); virtual BOOL OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult ); virtual BOOL OnWndMsg( UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult ); </pre>具体实现如下Q实C我将l出原有代码的主要部分以及修改后的代码以作对比?br />在cpp文g中加入下面的枚Dcd?<br /><pre>enum HitTestValue { noHit = 0,//表示没有选中M对象 vSplitterBox = 1, hSplitterBox = 2, bothSplitterBox = 3, vSplitterBar1 = 101,//代表各个方向的水q_割条 vSplitterBar15 = 115, hSplitterBar1 = 201,//代表垂直方向的各个分割条 hSplitterBar15 = 215, splitterIntersection1 = 301,//代表各个交叉? splitterIntersection225 = 525 }; <br /> CWnd* CxSplitterWnd::GetActivePane(int* pRow, int* pCol) { ASSERT_VALID(this); //获得当前的获得焦点的H口 //下面注释_体的是原有的代码的主要部分? // CWnd* pView = NULL; //CFrameWnd* pFrameWnd = GetParentFrame(); //ASSERT_VALID(pFrameWnd); //pView = pFrameWnd->GetActiveView(); //if (pView == NULL) // pView = GetFocus(); CWnd* pView = GetFocus(); if (pView != NULL && !IsChildPane(pView, pRow, pCol)) pView = NULL; return pView; } void CxSplitterWnd::SetActivePane( int row, int col, CWnd* pWnd) { CWnd* pPane = pWnd == NULL ? GetPane(row, col) : pWnd; //下面加注释粗体的是原有代码的主要部分? //FrameWnd* pFrameWnd = GetParentFrame(); //ASSERT_VALID(pFrameWnd); //pFrameWnd->SetActiveView((CView*)pPane); pPane->SetFocus();//修改后的语句 } void CxSplitterWnd::StartTracking(int ht) { ASSERT_VALID(this); if (ht == noHit) return; // GetHitRect will restrict ''''m_rectLimit'''' as appropriate GetInsideRect(m_rectLimit); if (ht >= splitterIntersection1 && ht <= splitterIntersection225) { // split two directions (two tracking rectangles) int row = (ht - splitterIntersection1) / 15; int col = (ht - splitterIntersection1) % 15; GetHitRect(row + vSplitterBar1, m_rectTracker); int yTrackOffset = m_ptTrackOffset.y; m_bTracking2 = TRUE; GetHitRect(col + hSplitterBar1, m_rectTracker2); m_ptTrackOffset.y = yTrackOffset; } else if (ht == bothSplitterBox) { // hit on splitter boxes (for keyboard) GetHitRect(vSplitterBox, m_rectTracker); int yTrackOffset = m_ptTrackOffset.y; m_bTracking2 = TRUE; GetHitRect(hSplitterBox, m_rectTracker2); m_ptTrackOffset.y = yTrackOffset; // center it m_rectTracker.OffsetRect(0, m_rectLimit.Height()/2); m_rectTracker2.OffsetRect(m_rectLimit.Width()/2, 0); } else { // only hit one bar GetHitRect(ht, m_rectTracker); } //下面加注释的从E序中删厅R? //CView* pView = (CView*)GetActivePane(); //if (pView != NULL && pView->IsKindOf(RUNTIME_CLASS(CView))) //{ // ASSERT_VALID(pView); // CFrameWnd* pFrameWnd = GetParentFrame(); //ASSERT_VALID(pFrameWnd); //pView->OnActivateFrame(WA_INACTIVE, pFrameWnd); // } // steal focus and capture SetCapture(); SetFocus(); // make sure no updates are pending RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW); // set tracking state and appropriate cursor m_bTracking = TRUE; OnInvertTracker(m_rectTracker); if (m_bTracking2) OnInvertTracker(m_rectTracker2); m_htTrack = ht; SetSplitCursor(ht); } BOOL CxSplitterWnd::OnCommand(WPARAM wParam, LPARAM lParam) { if (CWnd::OnCommand(wParam, lParam)) return TRUE; //下面_体的是原程序的语句 //<b>return GetParentFrame()->SendMessage(WM_COMMAND, wParam, lParam); </b> return GetParent()->SendMessage(WM_COMMAND, wParam, lParam); } BOOL CxSplitterWnd::OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult ) { if (CWnd::OnNotify(wParam, lParam, pResult)) return TRUE; //下面_体的是源程序的语句 //<b>*pResult = GetParentFrame()->SendMessage(WM_NOTIFY, wParam, lParam);</b> *pResult = GetParent()->SendMessage(WM_NOTIFY, wParam, lParam); return TRUE; } BOOL CxSplitterWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) { // The code line below is necessary if using CxSplitterWnd in a regular dll // AFX_MANAGE_STATE(AfxGetStaticModuleState()); return CWnd::OnWndMsg(message, wParam, lParam, pResult); } </pre>q样我们可以在对话框中使用CxSplitterWndcM?<br /><br /><b>四、CSplitterWnd的扩?/b><br />CSplitterWnd扩展话题是很多的Q我们可以通过对原有方法的覆盖或者增加新的方法来扩展CSplitterWnd。我们在此仅举两个方面的例子?<br /><b>4.1锁定切分?/b><br />当用户创建好分割H口后,有时q不希望通过拖动切分条来调节H口的大。这时就必须锁定切分条。锁定切分条的最单的Ҏ莫过于不让CSplitterWnd来处理WM_LBUTTONDOWN,WM_MOUSEMOVE,WM_SETCURSOR消息Q而是这些消息交lCWndH口q行处理Q从而屏蔽掉q些消息。拿WM_LBUTTONDOWN处理q程来说。修改ؓ如下Q?<br /><pre>void CXXSplitterWnd::OnLButtonDown(UINT nFlags,CPoint point) <br />{ CWnd::OnLButtonDown(nFlags,point); } </pre>其余的处理方法类伹{?<br /><b>4.2切分条的定制</b><br />由Window自己生成的切分条L固定的,没有M的变化,我们在用一些Y件比如ACDSee的时候却能发现它们的切分条却是和自动生成的切分条不一L。那么如何定制自q切分条呢Q通过重蝲CSplitterWnd的虚ҎOnDrawSplitter和OnInvertTracker可以辑ֈq样的目的。下面的代码生成的效果是分割H口的边界颜色ؓU色Q分割条的颜色ؓl色.代码如下Q?br /><pre>void CSplitterWndEx::OnDrawSplitter(CDC *pDC, ESplitType nType, const CRect &rectArg) { if(pDC==NULL) { RedrawWindow(rectArg,NULL,RDW_INVALIDATE|RDW_NOCHILDREN); return; } ASSERT_VALID(pDC); CRect rc=rectArg; switch(nType) { case splitBorder: //重画分割H口边界,使之为红? pDC->Draw3dRect(rc,RGB(255,0,0),RGB(255,0,0)); rc.InflateRect(-CX_BORDER,-CY_BORDER); pDC->Draw3dRect(rc,RGB(255,0,0),RGB(255,0,0)); return; case splitBox: pDC->Draw3dRect(rc,RGB(0,0,0),RGB(0,0,0)); rc.InflateRect(-CX_BORDER,-CY_BORDER); pDC->Draw3dRect(rc,RGB(0,0,0),RGB(0,0,0)); rc.InflateRect(-CX_BORDER,-CY_BORDER); pDC->FillSolidRect(rc,RGB(0,0,0)); pDC->Draw3dRect(rc,RGB(0,0,0),RGB(0,0,0)); return; case splitBar: //重画分割条,使之为绿? pDC->FillSolidRect(rc,RGB(255,255,255)); rc.InflateRect(-5,-5); pDC->Draw3dRect(rc,RGB(255,0,0),RGB(255,0,0)); return; default: ASSERT(FALSE); } pDC->FillSolidRect(rc,RGB(0,0,255)); } void CSplitterWndEx::OnInvertTracker(CRect &rect) { ASSERT_VALID(this); ASSERT(!rect.IsRectEmpty()); ASSERT((GetStyle()&WS_CLIPCHILDREN)==0); CRect rc=rect; rc.InflateRect(2,2); CDC* pDC=GetDC(); CBrush* pBrush=CDC::GetHalftoneBrush(); HBRUSH hOldBrush=NULL; if(pBrush!=NULL) hOldBrush=(HBRUSH)SelectObject(pDC->m_hDC,pBrush->m_hObject); pDC->PatBlt(rc.left,rc.top,rc.Width(),rc.Height(),BLACKNESS); if(hOldBrush!=NULL) SelectObject(pDC->m_hDC,hOldBrush); ReleaseDC(pDC); } </pre>同样我们只要l承CSplitterWnd中的其余的一些虚拟方法就可以生成h自己个性的分割H口了?br /><br />我的电子信箱Qtingya@njpost.com.cn 和tingya@263.net <br />地址Q南京邮政局计算Z?张中?<br />邮政~码Q?10008 </td> </tr> </tbody> </table> </div> </td> </tr> </tbody> </table> <img src ="http://www.shnenglu.com/microli/aggbug/11913.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/microli/" target="_blank">铁观?/a> 2006-09-01 09:56 <a href="http://www.shnenglu.com/microli/articles/11913.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC++实现混合静态分裂视H的Ҏhttp://www.shnenglu.com/microli/articles/11911.html铁观?/dc:creator>铁观?/author>Fri, 01 Sep 2006 01:54:00 GMThttp://www.shnenglu.com/microli/articles/11911.html 摘要 本文以MFCQMicrosoft Foundation Class LibraryQ的CsplitterWndcd为基Q通过对单文档视窗的静态分裂原理进行分析,介绍混合静态分裂视H的实现ҎQƈ深入阐述子视H的视图动态切换技术?/p>

关键?/b> 静态分裂视H?动态切换视?混合分裂视窗

前言

在许多视H应用Y件中Q通常要在屏幕上同时显Cq个子视H,以显C同一个文档的不同部分Q或者是在每个视H中分别昄不同文档的内宏Vؓ了实现多视窗界面Q可以采用MDI(Multiple Document Interface)的多文档模式q行处理Q但是多文档的应用程序设计与l护相对于单文档的应用程序而言比较复杂。而且Q如果要在屏q上同时昄多个子视H,通常要利用视H重叠函数进行管理,每个子视H的位置往往需要用鼠标Zؓ讑֮Q过多的Zؓq预降低了程序用的效率。因此,如果能对单文档视H做适当的分裂,无疑E序使用者将可以得到更易于操作的接口Q数据的昄也更加直观和方便。本文通过对单文档视窗的静态分裂原理进行分析,实现上述要求?

二分裂视H的cd

视窗的分裂可分ؓ两种cdQ一是动态分裂,二是静态分裂。动态分裂可以让使用者通过拖曳分裂方块的用,视H分裂。但是,动态分裂最多只可以视H分裂ؓ2×2个子视窗Q不能进行؜合分裂视H,所有子视窗的属性和父视H都是一LQ而且子视H的数据通常来源于同一处。而静态分裂,使用者除了可以调整子视窗的大和q行混合分裂视窗外,最多可视H分裂ؓ16×16个子视窗Q每个子视窗可以有各自不同的视图c?CView)Q各个子视窗昄的数据可以来自于不同的数据源。不论是要创建动态分裂视H还是静态分裂视H,都必要利用MFC的CSplitterWndcd来完成视H的分裂?/p>

混合静态分裂视H的实现

混合分裂视窗是指在子视窗中进行视H的再分裂。在MFC的框架下Q؜合分裂视H必d成三件工作:

⑴在视窗框架cd中定义CSplitterWnd控g为其属性(数据成员Q?/p>

⑵重载视H框架类别中的OnCreateClient函数QCFrameWnd::OnCreateClientQ,建立静态分裂子视窗Qؓ静态分裂子视窗填充视图?/p>

⑶徏立维持各子视H同步更新的机制?/p>

首先Q利用MFC AppWizard生成一个单文档应用E序Q在应用E序的CMainFramecd中声明CSplitterWndcd的数据成员?/p>

其次Q重载CMainFramecd中的OnCreateClient(LPCREATESTRUCT,CCreateContext* pContext)函数。在该函C利用CsplitterWndcd的构造函数Create Static(CWnd *pParentWnd,int nRows,int nCols,DWORD dwstyle,UINT nID) 创徏混合静态分裂子视窗Q即在Create Static分裂出的子视H中利用CsplitterWndcd的控件再一ơ分裂视H?/p>

Create Static函数的参数含义ؓQ?/p>

·pParentWnd是准备徏立静态分裂视H的视窗框架控g的指针;

·nRows和nCols是准备徏立静态分裂视H行敎ͼnRowsQ与列数QnColsQ?/p>

因此Q创建的静态分裂子视窗个数为nRows × nCols个,q两个参数最不得小?Q最大不可超q?6Qdwstyle是设定子视窗的Ş式;nID静态分裂的代号QIDQ,此代号预设ؓAFX_IDW_PANE_FIRSTQ若静态分裂视H位于另一个分裂视H内Ӟ不可以用默认|可以利用CsplitterWndcd的成员函数IdFromRowCol(int row,int col)获得。利用CsplitterWndcd的成员函数Create View (int row,int col,CruntimeClass* pViewClass,SIZE sizeinit,CcreateContext* pContext) 为静态分裂子视窗填充视图Q在视图与子视H关联时必须先完成子视窗的创建?/p>

Create View函数的参数含义ؓQ?

·row和col是指定准备徏立View控g的子视窗Q其指定的方式是以表C子视H所在的行列位置Q?/p>

·pViewClass是指定用于徏立子视窗View控g的ViewcdQ该cd需要被声明为Run-TimecdQ?/p>

·Sizeini是View控g的v始大;pContext是一个指向记录应用程序所使用的视H框架控件、Document控gQ以及View控g之变量的指针Q此参数在CMainFrame::OnCreateClient函数被调用时传入Q再p函数传递给此函数?/p>

·CsplitterWndcd的成员函数SetColumnInfo(int col,int cxIdeal,int cxMin)和SetRowInfo(int row,int cyIdeal,cyMin)|子视窗的宽度和高度Q参数cxIdeal和cxMin是指定子视窗的宽度和最宽度,cyIdeal和cyMin是指定子视窗的高度和最高度,在用这两个函数调整子视H的大小后还应该使用该类别的成员函数RecalLayout()重新调整视窗框架的布局。如果要讑֮视窗框架里的zd子视H,可以通过CsplitterWndcd的成员函数SetActivePane(int row,int col,CWnd* pWnd=NULL)来完成,该函数指定子视窗的方式有两种Q一是指出子视窗所在的行列Q二是传入指向该子视H的控g指针?/p>

最后,视H分裂成多个子视H后Q整个视H程序中存在多个View控g。当在其中一个View控g执行更新操作Ӟ如何让其它View控g同步更新数据Q可以通过文档cdQCDocumentQ的UpdateAllViews(CView* pSender,LPARAM lHint,CObject* pHint)成员函数的调用,再由该函数分别调用目前存在于视窗E序中各View控g的On Update函数来完成数据的同步更新?/p>

UpdateAllViews函数的参数含义ؓQ?/p>

·pSender是指向引发更新操作的View控g指针Q如果传入NULL表示所有视N要执行更新操作;

·lHint是用于传送更新视图时Q需要传送的额外信息参数Q?/p>

·pHint是指向记录更新视图所需额外信息的控件。在调用该函数时Q将View控g的指针传入的目的是要告诉该函数该子视囑ַl完成数据更斎ͼ该函C需要再调用该子视图的On Updateq行数据更新?/p>

子视囄动态切?/b>

在多视图应用E序中,可以通过改变CCreateContext对象的|来创建更加灵zȝ视图Q实现多视图的动态切换。CCreateContext是MFC框架所使用的一U数据结构,它将构成文档/视图l构的组件联pv来。这个结构包括指向文档的指针、视H框架的指针、视囄指针以及文档模板的指针,它还包含一个指向CRuntimeClassl构的指针,以指明所创徏的视囄cd?/p>

其数据成员如下:

·m_pNewViewClass是指向创Z下文的视囄CRuntimeClassl构的指针;

·m_pNewDocTemplate是指向与视窗框架的创建相联系的文档模板的指针Q?/p>

·m_pCurrentDoc是指向文档对象的指针Q以和新视图联系hQ?/p>

·m_pLastView是指向已存在的视囄指针Q它是新产生的视囄模型Q?/p>

·m_pCurrentFrame是指向已存在的视H框架的指针Q它是新产生的视H框架的模型?/p>

此外QQ何一个从CObjectcdl承而来的子cdQ在使用宏DECLARE_DYNAMIC、DECLARE_DYNCREATE、DECLARE_SERIAL三个中的L一个时都会产生一个CRuntimeClassl构的静态对象,RUNTIME_CLASSq回的就是这个对象的指针Q这个对象包含了其基cd本n在运行时ȝ信息?/p>

在单文档静态分裂视H的应用E序中,利用CsplitterWndcd的成员函数Delete View(int row,int col)可以删除子视H的原有视图Q然后再通过该类别的成员函数Create View为子视窗创徏新的视图。但是,创徏新视囑։必须初始化创Z下文相关指针Q即对CCreateContextl构赋倹{值得注意的是Q用Create View函数创徏的新视图不能自动调用视图cd的成员函数OnInitialUpdate和自动显Cƈ且激zL视图Q需要h工调用OnInitialUpdate函数和ShowWindow(SW_SHOW) 函数Q这些函数的调用都可以通过CsplitterWndcd的成员函数Get Pane(int row,int col)获得新视囄指针来完成?/p>

l束?/b>

在MFC的框架下Q؜合分裂视H有多种~程ҎQ本文只是从CsplitterWndcd的角度去分析混合静态分裂视H的实现ҎQ希望能l读者v到抛砖引玉的作用?

 



]]>
VC中用ListCtrll验ȝ(1)http://www.shnenglu.com/microli/articles/11499.html铁观?/dc:creator>铁观?/author>Sun, 20 Aug 2006 11:28:00 GMThttp://www.shnenglu.com/microli/articles/11499.html故ȝ了一下自q使用l验Q以供参考用?/p>

  先注明一下,q里Q我们用m_listctrl来表CZ个CListCtrl的类对象Q?/p>

然后q里我们的ListCtrl都是report形式Q至于其他的如什么大图标Q小图标

的暂时不Ԍ毕竟report是大众话的用。其ơ,我们q里用条ƾ一Q条ƾ二

来描q第一点,W二点,q个是参照《Effective C++》的叫法Q俺觉得q么

叫比较COOL :)

 条款一Q设|ListCtrl的风?/p>

 在CSDN上常常看到有人问怎么讄风格的,他们ListCtrl的样子是一个列?/p>

Q有横条和竖条分界线Q然后选中一行,要整一行都选中Q而不是只有某一?/p>

被选中Q等{,q里l一个比较全面的讄Ҏ?/p>

//获得原有风格
 DWORD dwStyle = ::GetWindowLong(m_listctrl.m_hWnd, GWL_STYLE);
 dwStyle &= ~(LVS_TYPEMASK);
 dwStyle &= ~(LVS_EDITLABELS);

 //讄新风?br />    SetWindowLong(m_listctrl.m_hWnd, GWL_STYLE,

dwStyle,|LVS_REPORT|LVS_NOLABELWRAP|LVS_SHOWSELALWAYS);


 //讄扩展风格
 DWORD styles =

LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_CHECKBOXES;

 ListView_SetExtendedListViewStyleEx(m_listctrl.m_hWnd, styles,

styles );

其中LVS_EX_FULLROWSELECT 是前面说得整行选中

LVS_EX_GRIDLINES |格U(只适用与report风格的listctrlQ?/p>

LVS_EX_CHECKBOXES 前面加个checkbox

pListCtrl->SetExtendedStyle(  m_listctrl.GetExtendedStyle()

|LVS_EX_SUBITEMIMAGES);


q也是一个很重要的属性,q样的话Q可以在列表中加ICONQ记得windows?/p>

d理器吗Q你惛_得那Pq个属性也要加哦,q个我以后会讲的?/p>

条款二:加入列头

  q是一个比较实质的东西Q给列表框分列,然后加上列头

  代码说话Q来?/p>

  TCHAR rgtsz[2][10] = {_T("列头1"), _T("列头2")};
 
 LV_COLUMN lvcolumn;
 CRect rect;
 m_listctrl.GetWindowRect(&rect);
 for(int i=0;i<2;i++)
 {
   lvcolumn.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT
              | LVCF_WIDTH | LVCF_ORDER;
   lvcolumn.fmt = LVCFMT_LEFT;
   lvcolumn.pszText = rgtsz[i];
   lvcolumn.iSubItem = i;
   lvcolumn.iOrder = i;
   if(i==0)
   {
      lvcolumn.cx = rect.Width()*3/5 ;
   }
   else
     lvcolumn.cx = rect.Width()*2/5;
      

   m_listctrl.InsertColumn(i, &lvcolumn);
  }

q是插入两列的做法,你要插入20列?Q随便你Q依L葫芦~~

 lvcolumn.mask 中那个mask可以有各U属性,具体ȝmsdn吧,

 

条款三:把记录,插入列表框中

 int nIndex = m_listctrl.GetItemCount();

  LV_ITEM   lvitemAdd = {0};
  lvitemAdd.mask = LVIF_TEXT;
  lvitemAdd.iItem = nIndex ;
  lvitemAdd.iSubItem = 0;
  lvitemAdd.pszText =_T("毛毛1");;


  if (m_listctrl.InsertItem(&lvitemAdd) != -1)
  {
   LV_ITEM lvitem = {0};
   lvitem.mask = LVIF_TEXT;
   lvitem.iItem = nIndex ;
   lvitem.iSubItem = 1;
 
   lvitem.pszText =_T("毛毛2");
   m_listctrl.SetItem(&lvitem);
  
  }

nIndex 是当前的行数Q然后把新的一行,插在最下面Q?/p>

 

条款四:l列表中插入图标

 在report格式中,也能插入图标

 l箋代码说话

 m_image是个CImageList对象

 m_image.Create(16,16, TRUE|ILC_COLOR24, 3, 1);

 m_listctrl.SetImageList(&m_image,LVSIL_SMALL);

然后调用CImageList的成员函数int CImageList::Add( HICON hIcon );

把ICON插入到imagelistQ?/p>

 然后在插入记录的时?/p>

 lvitemAdd.mask = LVIF_TEXT; Q》 lvitemAdd.mask =

LVIF_TEXT|LVIF_IMAGE

 然后d一个lvitemAdd.iImage = n;

 q个n是imagelist中的序号Q表C是具体的哪一个图标,list么,呵呵

 

条款五: 插入记录时用额外的信息QlParam 的?/p>

   有时候,你想对于某一行,加入一些额外的信息Q那么就可以使用q个

lParam

  msdn是这么描q的Specifies the 32-bit value of the item

  我上ơ是Z在某一行加入一个信息,H口句柄Q然后是q么加的Q?/p>

  int nIndex = m_listctrl.GetItemCount();

  LV_ITEM   lvitemAdd = {0};
  lvitemAdd.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;
  lvitemAdd.iItem = nIndex ;
  lvitemAdd.iSubItem = 0;
  lvitemAdd.pszText =_T("毛毛1");;

  lvitemAdd.iImage = n;
  lvitemAdd.lParam = (LPARAM)hwnd;(某个H口的窗口句?


  if (m_listctrl.InsertItem(&lvitemAdd) != -1)
  {
   LV_ITEM lvitem = {0};
   lvitem.mask = LVIF_TEXT;
   lvitem.iItem = nIndex ;
   lvitem.iSubItem = 1;
 
   lvitem.pszText =_T("毛毛2");
   m_listctrl.SetItem(&lvitem);
  
  }

okQ这是一个比较全的例子的Q又揺CONQ又使用PARAM?/p>

条款六 Q 点击列表框,获取选中行信?/p>

  响应NM_CLICK消息Q如果你有MSDNQ可以看刎ͼ有专门关于listview?/p>

NM_CLICK的介l?/p>

void CMyDlg::OnItemClick(NMHDR* pNMHDR, LRESULT* pResult)
{
 // TODO: Add your control notification handler code here
 int nItem = -1;
 
 LPNMITEMACTIVATE lpNMItemActivate = (LPNMITEMACTIVATE)pNMHDR;

 if(lpNMItemActivate != NULL)
 {
     nItem = lpNMItemActivate->iItem;
 }

}

现在nItem是点击选中那行的index了,有了indexQ获取那行的信息q难?/p>

Q?/p>

懒汉_难,因ؓ你还没讲Q晕Q那ql说

 

条款七: Ҏ行的indexQ获取该行的信息

 直接上代码吧

 LV_ITEM lvitem = {0};
   lvitem.iItem = nIndex;
   lvitem.iSubItem = 0;
   lvitem.mask = LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;

m_listctrl.GetItem(&lvitem)

q样Q就把nindex,W一列的信息取出来了Q包括刚才我们加入的ICON,和那?/p>

额外信息Q窗口句柄)Q?/p>

比如我要获取H口句柄Q就可以hwnd = (HWND)lvitem.lParam;

mask 用来指明你想获取那些信息

具体可以查msdn中LVITEM Structure的定义和CListCtrl::GetItem

 

条款八:用程序选中某一行,使之选中

选中之 

m_listctrl.SetItemState

(nIndex,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);

不选中Q取消选中?/p>

m_listctrl.SetItemState(nIndex,0,LVIS_SELECTED|LVIS_FOCUSED);

 

条款九:获取当前所有选中的行Q多选)

  q个Q俺比较懒了,抄msdn的代码吧Q反正很?/p>

  

Example
// CListCtrl* pListCtrl = (CListCtrl*) GetDlgItem

(IDC_YOURLISTCONTROL);
ASSERT(pListCtrl != NULL);

POSITION pos = pList->GetFirstSelectedItemPosition();
if (pos == NULL)
   TRACE0("No items were selected!\n");
else
{
  while (pos)
  {
     int nItem = pList->GetNextSelectedItem(pos);
     TRACE1("Item %d was selected!\n", nItem);
     // you could do your own processing on nItem here
  }
}

 

条款十:删除条款九中选中的行

  q个相对前面九个条款是比较麻烦的Q因为如果你要删除多行的话。往往要出?/p>

  比如Q我现在要删除第0行和W?行(列表的行序列是从0开始的Q?/p>

  那么好啊。我来删?/p>

  m_listctrl.DeleteItem(0)

        m_listctrl.DeleteItem(1)

  恭喜你,错了Q我好开心啊 Q)

  因ؓ你删除第0行以后,下面的行会往上移Q那么原来的W?行就变成了第0行,那么你再 m_listctrl.DeleteItem(1)Q那么删除的是原来的W2行,真麻烦,

   所以,只有从下往上删Q才是安全的Q先删的Q不会媄响后面的操作Q?/p>

    m_listctrl.DeleteItem(1)

        m_listctrl.DeleteItem(0)

  但有时候,我们也不知道要删除哪些行Q只知道要删除选中的那些行Q像条款九中的那?/p>

   如果我们q是?/p>

   

POSITION pos = m_listctrl.GetFirstSelectedItemPosition();
if (pos == NULL)
   TRACE0("No items were selected!\n");
else
{
  while (pos)
  {
     int nItem = m_listctrl.GetNextSelectedItem(pos);
    

 m_listctrl.DeleteItem(nItem );

  }
}

你就{着收尸?/p>

q时候我们就要B4微Y了,cx有GetLastselectedItemPosition 和GetPrevSelectedItem

多写一Ҏ员函Cd :(

 没办法,办法自己惻Iq里有个W办?/p>

 POSITION  sSelPos = NULL;

 while(sSelPos = m_listctrl.GetFirstSelectedItemPosition())
 {
        int nSelItem = -1;
         nSelItem = m_listctrl.GetNextSelectedItem(sSelPos);

         if(nSelItem >= 0 && nSelItem<m_listctrl.GetItemCount())
       {

             好了Q这个nSelItem 是我们要的DD

      }

}

GetNextSelectedItemq个函数Q看msdn的用法,其实是返回第一个的indexQ然后走C一个选中的行去,所以这么做也是安全的,在实际中Q俺也是q么做的Q测试也通过Q没问题?/p>

当然Q还有个办法Q先通过GetFirstSelectedItemPosition和GetNextSelectedItem

来获取所有的选中行的indexQ然后把q些index攑ֈ一个数l里Q然后再从下往上删

唉真ȝ啊,q要不定数组Q不说用new在堆上开吧,那么一个vectorL要的吧,ȝ?/p>

所以我暂时是用上述的办法来删除Q也供大家参考,希望能找到更好的办法?/p>

 

好了Q今天就暂时先整理上q十炏Vlistctrl其他高的用法,|上资料也很多,我也暂时不ȝQ以后有Z再说吧?/p>

搞了好长旉啊,要睡觉去了,累死了 Q)



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=662462

[点击此处收藏本文]   毛毛发表?2006q?4?3?23:32:00

 
PPG 发表?006-04-14 22:50:00  IP: 222.94.6.*
好文章,收藏一?/div>

 
yyh9186 发表?006-06-20 17:11:00  IP: 221.122.51.*
您好Q我最q遇C隄的问题,看了您的文章后,我想您在listctrl斚w一定了解很透彻Q希望您能帮我解册个问题。描q如下:listctrl的托选功能,cM于windows托选功能。我分析分ؓ两种情况Q?1)按住鼠标左键q行托选;(2)按住鼠标左键Qƈ按下ctrl键进行托选?
q个问题我自己实在是搞不定了Q希望高手您l出代码Q我的邮?
yyh9186@163.comQmsn:yyh9186@hotmail.com

 
毛毛 发表?006-06-21 10:38:00  IP: 218.4.149.*
托选是什么,多选吗Q??

现在的listctrlQ如果选择那个多选的属性(控g属性里有)Q那么就是;(2)按住鼠标左键Qƈ按下ctrl键进行多选?

如果你想只是左键多选,那么
自己模拟?首先判断鼠标左键单击在了listCtrl里面,然后截莯个消?修改消息参数
WM_LBUTTONDOWN

WPARAM wParam
LPARAM lParam;
wParam
MK_CONTROL
The CTRL key is down.
wParam=MK_CONTROL
然后l箋传递这个消息就得了

俺没试过Q?知道行不?/div>


]]>CRichEditCtrl 文本编?/title><link>http://www.shnenglu.com/microli/articles/11482.html</link><dc:creator>铁观?/dc:creator><author>铁观?/author><pubDate>Sun, 20 Aug 2006 03:20:00 GMT</pubDate><guid>http://www.shnenglu.com/microli/articles/11482.html</guid><description><![CDATA[ <p align="center"> <span style="FONT-WEIGHT: bold; FONT-SIZE: 18px; FONT-FAMILY: Verdana" align="center">CRichEditCtrl 文本编辑(MSN/QQ常用控gQ?/span> </p> <p align="center">owg 转自Qvcmute Q?005-9-9 13:48:00Q?br /><br />//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////</p> <p> <font color="#008000"> <b>一.常见问题<br /></b> <br />a.可以~译,不能执行?/font> <br />AfxInitRichEdit();<br /><br /><font color="#008000">b.升默认的Riched版本(默认的有一些bug)</font>Q如可在InitInstance中添加LoadLibrary("RICHED20.DLL") 最后注?FreeLibrary<br /><br />如果是CRichEditView基类的可?br />BOOL CXXXXXXView::PreCreateWindow(CREATESTRUCT& cs)<br />{<br />    //装入rich edit version 2.0<br />    if (LoadLibraryA("RICHED20.DLL") == NULL)<br />     { <br />        AfxMessageBox(_T("Fail to load \"riched20.dll\"."),MB_OK | MB_ICONERROR);<br />        PostMessage(WM_QUIT,0,0);<br />        return FALSE;<br />       }<br /><br />       m_strClass = RICHEDIT_CLASSA;//for 2.0 class<br /><br />       return CRichEditView::PreCreateWindow(cs);<br />}<br /><br /><font color="#008000">c.最后追加行</font><br />richeditctrl.SetSel(-1, -1);<br />richeditctrl.ReplaceSel( (LPCTSTR)str );<br /><br /><font color="#008000">d.字数限制</font><br />CRichEditCtrl::LimitText(long nChars)<br /><br /><font color="#008000">e.换行切换<br /></font><br />CRichEditView的OnInitialUpdate()函数中加入下面两句:<br />m_nWordWrap = WrapNone;<br />WrapChanged(); <br />WrapChanged实际上也是调?br />ctrl.SetTargetDevice(NULL, 1); <font color="#008000">//m_nWordWrap == WrapNone</font><br />ctrl.SetTargetDevice(NULL, 0);<font color="#008000"> //m_nWordWrap == WrapToWindow</font><br />q有不常用的 m_nWordWrap == WrapToTargetDevice<br />ctrl.SetTargetDevice(m_dcTarget, GetPrintWidth());<br />如果是在Dialog中,可用SetTargetDeviceQ注意在属性里面加上want return<br /><br /><font color="#008000">f.有时候不希望带格式的数据_脓Q可通过PasteSpecial选择性粘?/font><br />pmyRichEditCtrl->PasteSpecial(CF_TEXT);<br /><br /><font color="#008000">g.随着输入随着自动滚动条滚动到最后一?/font><br />int nFirstVisible = pmyRichEditCtrl->GetFirstVisibleLine();<br />if (nFirstVisible > 0)<br />{<br />    pmyRichEditCtrl->LineScroll(-nFirstVisible, 0);<br />}<br />?br />m_cRichEdit.PostMessage(WM_VSCROLL, SB_BOTTOM,0);<br /><br /><br /><font color="#008000">h.讄UNDO的次?只能用在RICHED20以上Q即默认不支持,必须升)</font><br />SendMessage(EM_SETTEXTMODE,TM_MULTILEVELUNDO,0);<br />TM_MULTILEVELUNDO 支持多取?默认?.可通过EM_SETUNDOLIMIT讄最大次?<br />SendMessage(EM_SETUNDOLIMIT,100,0);<br /><br /><font color="#008000">i.响应OnChange</font><br />EM_SETEVENTMASK 讄 ENM_CHANGE <br />long lMask = GetEventMask();<br />lMask |= ENM_CHANGE;<br />lMask &= ~ENM_PROTECTED;<br />SetEventMask(lMask);<br /><br /><font color="#008000">j.讄只读</font><br />CRichEditCtrl::SetReadOnly( BOOL bReadOnly = TRUE );<br />通过讄PROTECTED实现选中的文本只读,参见<br />http://www.codeguru.com/Cpp/controls/richedit/article.php/c2401/<br /><br /><b><font color="#008000">?函数应用<br /></font></b><br /><font color="#008000">a.讄字体Q主要是通过SetSelectionCharFormatQ?br /></font><br />CHARFORMAT cf;<br /><br />rich.GetSelectionCharFormat(cf);<br /><br />cf.dwMask|=CFM_BOLD;<br /><br />cf.dwEffects|=CFE_BOLD;<font color="#008000">//讄_体Q取消用cf.dwEffects&=~CFE_BOLD;</font><br /><br />cf.dwMask|=CFM_ITALIC;<br /><br />cf.dwEffects|=CFE_ITALIC;<font color="#008000">//讄斜体Q取消用cf.dwEffects&=~CFE_ITALIC;</font><br /><br />cf.dwMask|=CFM_UNDERLINE;<br /><br />cf.dwEffects|=CFE_UNDERLINE;<font color="#008000">//讄斜体Q取消用cf.dwEffects&=~CFE_UNDERLINE;<br /></font><br />cf.dwMask|=CFM_COLOR;<br /><br />cf.crTextColor = RGB(255,0,0);<font color="#008000">//讄颜色<br /></font><br />cf.dwMask|=CFM_SIZE;<br /><br />cf.yHeight =200;<font color="#008000">//讄高度<br /></font><br />cf.dwMask|=CFM_FACE;<br /><br />strcpy(cf.szFaceName ,_T("隶书"));<font color="#008000">//讄字体</font><br /><br />rich.SetSelectionCharFormat(cf);<br /><br /><font color="#008000">b.讄字体的行间距<br /></font><br />要用richedit2.0以上试试<br /><br />PARAFORMAT2 pf;<br />pf.cbSize = sizeof(PARAFORMAT2);<br />pf.dwMask = PFM_NUMBERING | PFM_OFFSET;<br />pf.wNumbering = PFN_BULLET;//注意PFM_NUMBERING <br />pf.dxOffset = 10;<br />VERIFY(SetParaFormat(pf)); <br /><br />常用的dwMask?br /><br />1 PFM_NUMBERING 成员 wNumbering 才v作用Q项目符P默认用PFN_BULLET<br />2 使用阿拉伯数?(1, 2, 3, ...). <br />3 使用写字母 (a, b, c, ...). <br />4 使用大写字母 (A, B, C, ...). <br />5 使用写|马数字 (i, ii, iii, ...). <br />6 使用大写|马数字 (I, II, III, ...). <br />7 自定义,字符见成?wNumberingStart. <br />PFM_OFFSET 成员 dxOffset 才v作用Q羃q,单位twips<br />PFM_STARTINDENT 成员 dxStartIndent 才v作用Q首行羃q?br />PFM_SPACEAFTER 成员 dySpaceAfter 才v作用Q段间距<br />PFM_LINESPACING 成员 dyLineSpacing 才v作用Q行间距<br /><font color="#008000"><br />c.讄CRichEditCtrl(2.0)背景透明 </font><br />long style = ::GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE);<br />style &= WS_EX_TRANSPARENT;<br />::SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE, style);<br />?CreateExQ然后把WS_EX_TRANSPARENT样式加上<br /><br /><font color="#008000">e.得到内容有三U?/font><br /><br />1)GetWindowText<br /><br />2)使用EM_GETTEXTEX<br /><br />GETTEXTEX gt;<br /><br />gt.cb = 200;<br /><br />gt.flags = GT_DEFAULT;<br /><br />gt.codepage = CP_ACP ;<br /><br />gt.lpDefaultChar = NULL; <br /><br />gt.lpUsedDefChar = NULL;<br /><br />SendMessage(EM_GETTEXTEX,(WPARAM)&gt,(LPARAM)text);</p> <p> <br />3)StreamOut(主要用于RTF{格式输?<br /><br />static DWORD CALLBACK <br />MyStreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)<br />{<br />    CFile* pFile = (CFile*) dwCookie;<br /><br />    pFile->Write(pbBuff, cb);<br /><br />    *pcb = cb;<br /><br />    return 0;<br />}<br /><br /><br />CFile cFile(TEXT("myfile.rtf"), CFile::modeCreate|CFile::modeWrite);<br /><br />EDITSTREAM es;<br /><br />es.dwCookie = (DWORD) &cFile;<font color="#008000">//讄用例参数,以便回调函数调用</font><br /><br />es.pfnCallback = MyStreamOutCallback; <br /><br />pmyRichEditCtrl->StreamOut(SF_RTF, es);<br /><br />d可以此类推,SetWindowText,EM_SETTEXTEX,StreamIn<br /><font color="#008000"><br />f.查找字符?br /></font><br />FINDTEXTEX ft;<br />ft.chrg.cpMin = 0;<br />ft.chrg.cpMax = -1;<br />ft.lpstrText = "|";<br />long lPos = FindText(0, &ft);<br /><br />如果要l查找,修改cpMin,?br />int nCount = 0;<br />do<br />{<br />   long lPos = GetRichEditCtrl().FindText(0, &ft);<br />   if( -1 == lPos) break;<br />   ft.chrg.cpMin = lPos + strlen(ft.lpstrText);<br />   ++nCount;<br />}while(TRUE);<br /><font color="#008000"><br />g.以Html格式保存<br /></font><br />目前做法可先转ؓRTF格式Q再通过RTF-to-HTML Converter<br />http://www.codeguru.com/Cpp/controls/richedit/conversions/article.php/c5377/<br /><br /><font color="#008000">h.重蝲OnProtected函数得到对应的消息,如粘贴等</font><br />void CMYichEditorView::OnProtected(NMHDR* pNMHDR, LRESULT* pResult)<br />{<br />   ENPROTECTED* pEP = (ENPROTECTED*)pNMHDR;<br /><br />   switch (pEP->msg) {<br />   case WM_KEYDOWN://按键Q判断pEP->wParam<br />   case WM_PASTE://_脓<br />   case WM_CUT://剪切<br />   case EM_SETCHARFORMAT:<br />   default:<br />   break;<br />};<br /><br />*pResult = FALSE;<br />}<br /><br /><font color="#008000"><b>?聊天常用 <br /></b></font><br /><font color="#008000">a.LINK 链接功能<br /></font><br />1. LoadLibrary(_T("Riched20.dll"));<br /><br />2. 创徏RichEdit2.0控g<br /><br />CreateEx(0, _T("RichEdit20A"), NULL, WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP<br />|ES_READONLY|ES_WANTRETURN|ES_MULTILINE,<br />rect.left, rect.top, cx, cy,<br />pParentWnd->m_hWnd, (HMENU)nID, NULL);<br /><br />3. 讑֮选中的文字ؓ链接昄<br />CHARFORMAT2 cf2;<br />ZeroMemory(&cf2, sizeof(CHARFORMAT2));//<br />cf2.cbSize = sizeof(CHARFORMAT2);<br />cf2.dwMask = CFM_LINK;<br />cf2.dwEffects |= CFE_LINK;<br />m_cRichEdit.SendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);<br /><br />4.支持链接的点d?br />m_cRichEdit.SetEventMask(ENM_LINK);<br /><br />5.响应链接的点击EN_LINK<br />BEGIN_MESSAGE_MAP(CMyRichEdit, CRichEditCtrl)<br />ON_NOTIFY_REFLECT(EN_LINK,OnURL)<br />END_MESSAGE_MAP()<br />......<br /><br />void CMyRichEdit::OnURLClick(NMHDR *pNmhdr, LRESULT *pResult)<br />{<br />    TCHAR LinkChar[512];<br />    ENLINK *pLink = (ENLINK *)pNmhdr;<br />    if (pLink->msg == WM_LBUTTONUP)<br />    {<br />        SetSel(penLink->chrg);<font color="#008000">//q是链接的文字范?/font><br />        long Res = GetSelText((char *)LinkChar);<font color="#008000">//q是链接文字</font><br />       <font color="#008000"> //后面是你的处理过E?/font><br />        ......<br />     }<br />}<br /><br /><font color="#008000">b.插入位图</font><br />http://www.codeguru.com/Cpp/controls/richedit/article.php/c2417/<br />http://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/<br /><br />自定义在RichEdit中插入对象的图标<br />http://www.blogcn.com/user3/jiangsheng/blog/1319738.html<br />Ҏ基本同Knowledge Base文章Q220844 HOWTO: Insert a Bitmap Into an RTF Document Using the RichEdit Control<br />只是在最后插入之前调用一下IOleCache::SetData,用一个HGLOBAL作ؓ参数QHGLOBAL里面的数据是一个METAFILEPICTl构Q包含自己提供的囄<br /><br />使用CRichEditView::InsertFileAsObject可以插入图像。VC++带有一个例子WordPad?br />另外可以参考“Insert any HBITMAP (Bitmap) in your RichEdit Control?http://www.codeguru.com/richedit/richeditrc.html)?<br /><font color="#008000"><br />c.昄GIF动画</font><br />常用的是通过qq的imageole.dll(也有用Gif89.dll?<br />http://www.xiaozhou.net/cooldog/blogview.asp?logID=82<br />http://www.codeproject.com/richedit/AnimatedEmoticon.asp<br /><br />在richedit控g中插入动态GIF (Native C++?<br />http://blog.joycode.com/jiangsheng/archive/2004/12/15/41209.aspx<br /><br />d.IRichEditOleCallback的?br />http://61.186.252.131/Expert/topic/905/905844.xml?temp=.8379022<br /><br />cM MSN 信息发送框的制??<br />http://www.vckbase.com/document/viewdoc/?id=1087<br />内容包含Q实现右键菜单,囄插入Q读?写入RTF格式字符?br /><br />自定?CRichEditCtrl 控g<br />http://www.vckbase.com/document/viewdoc/?id=328<br />内容包含Q鼠标右键消息,消息映射Q字体变?br /><br />PS.richedit控g升?.0后,先把字体设ؓ楷体Q输入汉字没有问题,但输入字母时Q字母自动蟩转ؓArial字体Q?.0却没有这个文题,仍然是用楷体昄字母<br />是一个专门的设计 Dual-font, Smart font apply, 参见 http://61.186.252.131/Expert/topic/913/913807.xml?temp=.3753778 <br />----------------------<br />比我惌中还要花旉Q所以最后R草了点,见谅</p> <br /> <img src ="http://www.shnenglu.com/microli/aggbug/11482.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/microli/" target="_blank">铁观?/a> 2006-08-20 11:20 <a href="http://www.shnenglu.com/microli/articles/11482.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【原】CEdit & CRichEdit 使用技?/title><link>http://www.shnenglu.com/microli/articles/11472.html</link><dc:creator>铁观?/dc:creator><author>铁观?/author><pubDate>Sat, 19 Aug 2006 16:34:00 GMT</pubDate><guid>http://www.shnenglu.com/microli/articles/11472.html</guid><description><![CDATA[【原】CEdit & CRichEdit 使用技?br />作者:lixiaosan<br />日期Q?4/07/2006<br /><br /><br />注:<br />        m_edit1代表ID为IDC_EDIT1的CEdit控g的controlcd的变?br />        m_richedit1代表ID为IDC_RICHEDIT1的CRichEditCtrl控g的controlcd的变?br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">1.讄edit只读属?br /><br /></span>    Ҏ一Q?br />                m_edit1.SetReadOnly(TRUE);<br />    Ҏ二:<br />                ::SendMessage(m_edit1.m_hWnd, EM_SETREADONLY, TRUE, 0);<br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">2.判断edit中光标状态ƈ得到选中内容(richedit同样适用)<br /><br /></span>        int nStart, nEnd;<br />        CString strTemp;<br /><br />        m_edit1.GetSel(nStart, nEnd);<br />        if(nStart == nEnd)<br />        {<br />            strTemp.Format(_T("光标?d"), nStart);<br />            AfxMessageBox(strTemp);<br />        }<br />        else<br />        {<br />            //得到edit选中的内容   ?<br />            m_edit1.GetWindowText(strTemp);<br />            strTemp = strTemp.Mid(nStart) - strTemp.Mid(nEnd);<br />            AfxMessageBox(strTemp); <br />        }<br />    注:GetSel后,如果nStart和nEndQ表明光标处于某个位|(直观来看是光标在闪动)Q?br />             如果nStart和nEnd不相{,表明用户在edit中选中了一D内宏V?br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">3.在edit最后添加字W串<br /><br /></span>        CString str;<br />        m_edit1.SetSel(-1, -1);<br />        m_edit1.ReplaceSel(str);<br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">4.随输入自动滚动到最后一?richedit同样适用)<br /><br /></span>    Ҏ一Q(摘自msdnQ?br />        // The pointer to my edit.<br />        extern CEdit* pmyEdit;<br />        int nFirstVisible = pmyEdit->GetFirstVisibleLine();<br /><br />        // Scroll the edit control so that the first visible line<br />        // is the first line of text.<br />        if (nFirstVisible > 0)<br />        {<br />            pmyEdit->LineScroll(-nFirstVisible, 0);<br />        }<br />    Ҏ二:<br />        m_richedit.PostMessage(WM_VSCROLL, SB_BOTTOM, 0);<br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">5.如何限制edit输入指定字符<br /><br /></span>   可以从CEditz一个类Q添加WM_CHAR消息映射。下面一个例子实C限定输入16q制字符的功能?br /><br />   void CMyHexEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)  <br />   { <br />        if ( (nChar >= '0' && nChar <= '9') || <br />             (nChar >= 'a' && nChar <= 'f') || <br />             (nChar >= 'A' && nChar <= 'F') || <br />              nChar == VK_BACK ||  <br />              nChar == VK_DELETE)    //msdn的virtual key<br />       { <br />            CEdit::OnChar(nChar, nRepCnt, nFlags); <br />        }     <br />   }<br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">6.如何使用richedit<br /><br /></span>    dAfxInitRichEdit();<br />       CxxxApp::InitInstance()<br />        {<br />             AfxInitRichEdit();<br />          .............<br />       }<br /><br />   AfxInitRichEdit()功能Q装?RichEdit 1.0 Control (RICHED32.DLL).<br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">7.如何使用richedit2.0 or richedit3.0<br /><br /></span>    使用原因Q由于RichEdit2.0A自动为宽字符QWideCharQ,所以它可以解决中文q以及一些汉字问?br /><br />    Ҏ一Q(msdn上的做法Q适用于用VC.NET及以后版本创建的工程Q?br />            To update rich edit controls in existing Visual C++ applications to version 2.0,<br />            open the .RC file as text, change the class name of each rich edit control from   "RICHEDIT" to  "RichEdit20a". <br />            Then replace the call to AfxInitRichEdit with AfxInitRichEdit2.<br />    Ҏ二:以对话框ZQ?br />       (1)    增加一全局变量 HMODULE hMod;<br />       (2)    在CxxxApp::InitInstance()中添加一句hMod = LoadLibrary(_T("riched20.dll"));<br />              在CxxxApp::ExitInstance()中添加一句FreeLibrary(hMod);<br />       (3)      在对话框上放一个richeditQ文本方式打开.rc文g修改该richedit控g的类?RICHEDIT" to  "RichEdit20a".<br />       (4)      在对话框头文件添?CRichEditCtrl m_richedit;<br />              在OnInitDialog中添?m_richedit.SubclassDlgItem(IDC_RICHEDIT1, this);<br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">8.改变richedit指定区域的颜色及字体<br /><br /></span>        CHARFORMAT cf;<br />        ZeroMemory(&cf, sizeof(CHARFORMAT));<br />        cf.cbSize = sizeof(CHARFORMAT);<br />        cf.dwMask = CFM_BOLD | CFM_COLOR | CFM_FACE |<br />                            CFM_ITALIC | CFM_SIZE | CFM_UNDERLINE;<br />        cf.dwEffects = 0;<br />        cf.yHeight = 12*12;//文字高度<br />        cf.crTextColor = RGB(200, 100, 255); //文字颜色<br />        strcpy(cf.szFaceName ,_T("隶书"));//讄字体<br />     <br />        m_richedit1.SetSel(1, 5); //讄处理区域<br />        m_richedit1.SetSelectionCharFormat(cf);<br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">9.讄行间距(只适用于richedit2.0Q?br /><br /></span>        PARAFORMAT2 pf;<br />        pf2.cbSize = sizeof(PARAFORMAT2);<br />        pf2.dwMask = PFM_LINESPACING | PFM_SPACEAFTER;<br />        pf2.dyLineSpacing = 200;<br />        pf2.bLineSpacingRule  = 4;<br />        m_richedit.SetParaFormat(pf2);<br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">10.richedit插入位图<br /><br /></span>Q220844QHow to insert a bitmap into an RTF document using the RichEdit control in Visual C++ 6.0<br /><a >http://support.microsoft.com/default.aspx?scid=kb;en-us;220844</a><br /><a >http://www.codeguru.com/Cpp/controls/richedit/article.php/c2417/</a><br /><a >http://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/</a><br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">11.richedit插入gif动画<br /><a ><br /></a></span><a href="javascript:void(0);/*1144809701660*/">http://www.codeproject.com/richedit/AnimatedEmoticon.asp</a><br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">12.richedit嵌入ole对象<br /><br /></span><a >http://support.microsoft.com/kb/141549/en-us</a><br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">13.使richedit选中内容只读<br /><br /></span><a >http://www.codeguru.com/cpp/controls/richedit/article.php/c2401/</a><br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">14.打印richedit</span><span style="COLOR: rgb(0,0,0)"><br /><br /><a >http://www.protext.com/MFC/RichEdit3.htm</a></span><br /><a ><span style="COLOR: rgb(0,0,0)"></span></a><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">15.richeidt用于聊天消息H口<br /><br /></span><a >http://www.vckbase.com/document/viewdoc/?id=1087</a><br /><a >http://www.codeproject.com/richedit/chatrichedit.asp</a><br /><a >http://www.codeguru.com/Cpp/controls/richedit/article.php/c2395/</a><br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">16.解决richedit的EN_SETFOCUS和EN_KILLFOCUS无响应的问题<br /><br /></span><a >http://support.microsoft.com/kb/181664/en-us</a><br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">17.richedit拼写?br /><br /></span><a >http://www.codeproject.com/com/AutoSpellCheck.asp</a><br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">18.改变edit背景?br /><br /></span>Q117778QHow to change the background color of an MFC edit control<br /><a >http://support.microsoft.com/kb/117778/en-us</a><br /><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">19.当edit控g的父H口属性是带标题栏WS_CAPTION和子H口WS_CHILDӞ不能讄焦点SetFocus<br /><br /></span>Q230587QPRB: Can't Set Focus to an Edit Control When its Parent Is an Inactive Captioned Child Window<br style="COLOR: rgb(153,51,0)" /><span style="COLOR: rgb(153,51,0)"><a ><span style="COLOR: rgb(153,51,0)">http://support.microsoft.com/kb/230587/en-us</span><br style="COLOR: rgb(153,51,0)" /></a></span><br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">20. 在Edit中回车时Q会退出对话框  </span><br /><br />选中Edit的风格Want Return?br /><br />MSDN的解释如下:<br /><font size="+0"><font face="verdana,arial,helvetica" size="2"><strong>ES_WANTRETURN</strong>   Specifies that a carriage return be inserted when the user presses the ENTER key while entering text into a multiple-line edit control in a dialog box. Without this style, pressing the ENTER key has the same effect as pressing the dialog box's default pushbutton. This style has no effect on a single-line edit control.<br /><br /></font></font><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">21. 动态创建的edit没有Ҏ的问?/span><br /><br />    m_edit.Create(....);<br />    m_edit.ModifyStyleEx(0, WS_EX_CLIENTEDGE, SWP_DRAWFRAME);<br /><hr style="WIDTH: 100%; HEIGHT: 2px" /><span style="COLOR: rgb(153,51,0)">22. 一个能昄RTFQoleQ包括gifQ?wmvQexcel QpptQ的例子</span><br /><br /><a >http://www.codeproject.com/richedit/COleRichEditCtrl.asp</a><br /><br /><p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=652795</p><img src ="http://www.shnenglu.com/microli/aggbug/11472.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/microli/" target="_blank">铁观?/a> 2006-08-20 00:34 <a href="http://www.shnenglu.com/microli/articles/11472.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.ppxp.com.cn" target="_blank">޾ƷþþþĻ69 </a>| <a href="http://www.xuanhaoma.com.cn" target="_blank">þþSS鶹ŷպ</a>| <a href="http://www.forsagecn.cn" target="_blank">Ʒþ߹ۿ</a>| <a href="http://www.whoimi.cn" target="_blank">þWWW˳һƬ</a>| <a href="http://www.ssc860.cn" target="_blank">Ļþ</a>| <a href="http://www.ikxc.cn" target="_blank">þþĻձ</a>| <a href="http://www.forseor.cn" target="_blank">þþƷƷ</a>| <a href="http://www.huadublog.cn" target="_blank">þþþþþ92</a>| <a href="http://www.uyqr.cn" target="_blank">ƷŮþþþAV</a>| <a href="http://www.99341.cn" target="_blank">þŮˬŮˬ</a>| <a href="http://www.ominimo.cn" target="_blank">66ƷۺϾþþþþþ</a>| <a href="http://www.yunva.cn" target="_blank">þþƷŷƬ</a>| <a href="http://www.wdmdg.cn" target="_blank">޹˾þһWWW</a>| <a href="http://www.enepower.cn" target="_blank">ۺϾþþƷɫ</a>| <a href="http://www.sxjax.cn" target="_blank">þþƷ</a>| <a href="http://www.vtsg.cn" target="_blank">þɧ</a>| <a href="http://www.centralworld.cn" target="_blank">Ʒþøһ</a>| <a href="http://www.peizis.cn" target="_blank">þСƵ</a>| <a href="http://www.shuju365.com.cn" target="_blank">ѾþþƷѾѾ</a>| <a href="http://www.pzjc.net.cn" target="_blank">þþƷWWW456C0M</a>| <a href="http://www.epfx.cn" target="_blank">ŷƷۺϾþ</a>| <a href="http://www.hoay.com.cn" target="_blank">ŷղþ99</a>| <a href="http://www.dyfls.cn" target="_blank">þݺҹҹavapp</a>| <a href="http://www.hyattzhuzhou.cn" target="_blank">þþƷĻ̾</a>| <a href="http://www.uzfz.cn" target="_blank">ԭۺϾþ</a>| <a href="http://www.co1txk.cn" target="_blank">þ</a>| <a href="http://www.uukibu.cn" target="_blank">Ʒ׾þAAAƬ69</a>| <a href="http://www.foshai.cn" target="_blank">þۺŷ</a>| <a href="http://www.91368.com.cn" target="_blank">þóӰԺƷ777</a>| <a href="http://www.straddle.cn" target="_blank">þ޾Ʒҳ</a>| <a href="http://www.67yule.cn" target="_blank">þþþav</a>| <a href="http://www.igdl.cn" target="_blank">ŷ˾þƬ</a>| <a href="http://www.kaczw3.cn" target="_blank">ŷ޹׾þþþþþ </a>| <a href="http://www.8xpn.cn" target="_blank">㽶þ99</a>| <a href="http://www.92loc.cn" target="_blank">޾ƷþþþþͼƬ </a>| <a href="http://www.d2338.cn" target="_blank">ƷþþþӰ</a>| <a href="http://www.jacctv.cn" target="_blank">þþþһƷ</a>| <a href="http://www.rvyq.cn" target="_blank">ݺɫþۺ</a>| <a href="http://www.98sr.cn" target="_blank">Ʒþþþþþþþ</a>| <a href="http://www.anrf.cn" target="_blank">Ưޱ˾þþƷ</a>| <a href="http://www.touzhi8.cn" target="_blank">Ʒ˾þþþþþ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>