`
hcmfys
  • 浏览: 347720 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

得到1

 
阅读更多

<!-- [if !mso]> <style> v/:* {behavior:url(#default#VML);} o/:* {behavior:url(#default#VML);} w/:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} </style> <![endif]--><!-- [if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:PunctuationKerning/> <w:DrawingGridVerticalSpacing>7.8 磅</w:DrawingGridVerticalSpacing> <w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery> <w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:Compatibility> <w:SpaceForUL/> <w:BalanceSingleByteDoubleByteWidth/> <w:DoNotLeaveBackslashAlone/> <w:ULTrailSpace/> <w:DoNotExpandShiftReturn/> <w:AdjustLineHeightInTable/> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> <w:DontGrowAutofit/> <w:UseFELayout/> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> </w:WordDocument> </xml><![endif]--><!-- [if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" LatentStyleCount="156"> </w:LatentStyles> </xml><![endif]--><!-- [if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;} </style> <![endif]-->

// HitTestEx 
- Determine the row index and column index for a point
// Returns 
- the row index or -1 if point is not over a row
// point 
- point to be tested.
// col 
- to hold the column index
int
 CMyListCtrl::HitTestEx(CPoint &point, int
 *col) const

{
 
int
 colnum = 0;
 
int
 row = HitTest( point, NULL );
 

 
if
( col ) *col = 0;

 
// Make sure that the ListView is in LVS_REPORT

 
if
( (GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT )
 
return
 row;

 
// Get the top and bottom row visible

 
row = GetTopIndex();
 
int
 bottom = row + GetCountPerPage();
 
if
( bottom > GetItemCount() )
 
bottom = GetItemCount();
 

 
// Get the number of columns

 
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
 
int
 nColumnCount = pHeader->GetItemCount();

 
// Loop through the visible rows

 
for
( ;row <= bottom;row++)
 
{
 
// Get bounding rect of item and check whether point falls in it.

 
CRect rect;
 
GetItemRect( row, &rect, LVIR_BOUNDS );
 
if
( rect.PtInRect(point) )
 
{
 
// Now find the column

 
for
( colnum = 0; colnum < nColumnCount; colnum++ )
 
{
 
int
 colwidth = GetColumnWidth(colnum);
 
if
( point.x >= rect.left 
 
&& point.x <= (rect.left + colwidth ) )
 
{
 
if
( col ) *col = colnum;
 
return
 row;
 
}
 
rect.left += colwidth;
 
}
 
}
 
}
 
return
 -1;
}

CListCtrl 类成员

CListCtrl::HitTest

int HitTest(LVHITTESTINFO* pHitTestInfo) const
int HitTest(CPoint pt,UINT* pFlags=NULL) const

返回值:
返回参数pHitTestInfo 指定位置的项的索引,否则为-1

参数: pHitTestInfo 含有要进行击中测试的位置以及接受击中测试有关结果信息的LVHITTESTINFO 结构的地址。
pt
被测试的指针。
pFlags
指向接受测试结果信息的整数的指针。请参阅联机文档 平台SDK” 中有关LVHITTESTINFO 结构的flags 成员的注解。

说明:
如果有,则决定哪一个列表视图项在指定的位置上。
可以通过使用结构中flags 成员的LVHT_ABOVE, LVHT_BELOW,LVHT_TOLEFT 以及LVHT_TORIGHT 的值来决定是否滚动列表视图控件的内容。上述两种标志可以自由组合,例如,假设其位于客户区域的左上角。
可以通过测试结构中flags 成员的LVHT_ONITEM 值来决定是否给定的位置位于列表视图项的上方。该数值通过结构flags 成员中的 LVHT_ONITEMICONLVHT_ONITEMLABEL,LVHT_ONITEMSTATEICON 的值的位或运算而获取。

HitTest :得到当前鼠标位置的Item

其实关键是要有ScreenToClient 这个函数的使用,我先前没有用这个函数,HitTest 老是返回-1, 搞得我都头大了。不过这个不能用于SubItem, 那应该要用SubItemHitTest

CListCtrl中的HitTest、SubItemHitTest的用法 - happymengqiang - happymengqiang的博客 LVHITTESTINFOht;

CListCtrl中的HitTest、SubItemHitTest的用法 - happymengqiang - happymengqiang的博客 GetCursorPos(&(ht.pt));

CListCtrl中的HitTest、SubItemHitTest的用法 - happymengqiang - happymengqiang的博客 m_friendList.ScreenToClient(&ht.pt);

CListCtrl中的HitTest、SubItemHitTest的用法 - happymengqiang - happymengqiang的博客 m_friendList.HitTest(&ht);

CListCtrl中的HitTest、SubItemHitTest的用法 - happymengqiang - happymengqiang的博客 if(ht.iItem==-1)  // 检查是否有item 选中

CListCtrl中的HitTest、SubItemHitTest的用法 - happymengqiang - happymengqiang的博客 return;

SubItemHitTest

void CTest6Dlg::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult)
{
/****************************************/
/*
确定单击的listctrl 的行列号 方法1 */
/****************************************/

/*
DWORD dwPos = GetMessagePos();
CPoint point( LOWORD(dwPos), HIWORD(dwPos) );

m_list.ScreenToClient(&point);

LVHITTESTINFO lvinfo;
lvinfo.pt = point;
lvinfo.flags = LVHT_ABOVE;

int nItem = m_list.SubItemHitTest(&lvinfo);
if(nItem != -1)
{
CString strtemp;
strtemp.Format( "
单击的是第%d 行第%d ", lvinfo.iItem, lvinfo.iSubItem);
}
*pResult = 0;
}

双击时鼠标所在的位置。下面我们就再来为 CScheduleView 添加一个处理 NM_DBLCLK 通知消息的处理函数 OnDblclk() ,并输入下面的实现代码:
void CScheduleView::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult) {
if( ((LPNMLISTVIEW) pNMHDR)->iItem != -1 )
GetDocument()->OnEdittask();
*pResult = 0;
}
这个函数比较有意思,它的第一个参数本来是一个指向 NMHDR 结构的指针,然而在函数体中我们却将之强制转换成指向一个 NMLISTVIEW 结构的指针,为什么呢?原因是 4.71 版及更高版本的 List 控件( IE 4.0 之后的 List 控件都满足版本要求)在发送通知消息 NM_DBLCLK 的时,实际上传递的是
一个 NMLISTVIEW 结构的指针,但标准的 NM_DBLCLK 消息传递的却是 NMHDR 结构的指针, ClassWizard 在生成函数框架时是按照标 准消息格式来处理的。 NMLISTVIEW 结构除了在开头部分包含了一个 NMHDR 结构外,它还提供了被双击项目的相关信息,如果它的 iItem 成员等于 -1 ,则表示用户不是对
着一个项目双击的,如果是这样的话,我们也就不必调用 OnEdittask() ,从而避免了出现不必要的操作提示信息。实际上, OnLButtonDblClk() 也可以实现 OnDblclk() 的这个功能,但需要将相关代码改为:
if( GetListCtrl().GetSelectedCount() == 1 )
GetDocument()->OnEdittask();
现在这两个函数的功能就基本一致了,朋友们可以任意保留其中一个函数,而把另一个函数删掉,当然,今后在编写其它程序时 OnLButtonDblClk() OnDblclk() 就不一定能做到等价了。另外,大家不妨进一步研究一下 WM_LBUTTONDBLCLK NM_DBLCLK 之间的关系,解释为什么用户的一次双
击能引发这两种消息,它们的发生顺序又如何等等。
接下来我们再次利用 ClassWizard CScheduleView 添加一个处理 WM_RBUTTONDOWN 消息的函数 OnRButtonDown() ,准备在其中弹出一个关联菜单。
编辑和使用弹出式菜单
关联菜单实质上是一种弹出式菜单,通常情况下,弹出式菜单相当于主菜单的一个子菜单项。我们打开资源编辑器,添加一个新的菜单资源,修改其 ID IDR_TASKMENU ,然后在第一个顶级菜单项下面添加三个命令,它们与程序主菜单的 " 安排 " 子菜单下面的命令完全一样,包括 ID Caption
Prompt 。编辑完毕后,以 Popup 方式来查看 IDR_TASKMENU ,其效果应如图 18-1 所示。
现在我们来为 OnRButtonDown() 编写实现代码:
void CScheduleView::OnRButtonDown(UINT nFlags, CPoint point) {
CMenu tmpMenu;
CMenu* pSubMenu;
tmpMenu.LoadMenu(IDR_TASKMENU); //
装载菜单资源
pSubMenu=tmpMenu.GetSubMenu(0); //
获得子菜单的指针
ClientToScreen(&point); //
将客户区的坐标位置转换成屏幕坐标位置
pSubMenu->TrackPopupMenu( TPM_RIGHTBUTTON|TPM_LEFTALIGN|TPM_TOPALIGN, point.x, point.y, this,0 ); //
显示弹出式菜单
tmpMenu.DestroyMenu(); //
释放菜单资源
}
在上面的代码中, LoadMenu() 用于装载菜单资源 IDR_TASKMENU ,由于我们使用了局部变量来存放不属于任何一个窗口的菜单对象,所以在退 OnRButtonDown() 函数之前必须释放相应的菜单资源,否则多次调用该函数之后,程序将会占掉不少的系统资源。
ClientToScreen()
的作用是将客户区的坐标位置转换成屏幕坐标位置,因为 WM_RBUTTONDOWN 消息中的鼠标位置参数是相对于客户区 的,而 TrackPopupMenu() 函数的参数必须是基于屏幕坐标系的,如果不经过一次转换,菜单弹出的位置就不知道会偏到哪里去了。
现在我们来运行一下 Schedule ,在客户区内单击鼠标右键,就会弹出如图 18-2 所示的关联菜单,选择命令之后它就会调用相应的处理函数。
到本讲为止, Schedule 的编程工作也就要告一段落了, Schedule 只是心铃用来讲解 VC 编程的一个实例,它的功能很单一,但仍有一定的实用价 值。已经用惯了各种优秀软件的朋友肯定不会满足于现在的 Schedule ,因为它现在只是一只丑小鸭而已,要把它变成一只天鹅还需要我们更多的辛
勤劳动,心铃在下面列出了一些可能的改进,希望已经喜爱上 VC 编程的朋友们自已动手来进一步修饰 Schedule
1
.删除 Schedule 中一些不必要的菜单命令和工具栏上的按钮;
2
.根据用户选中事件条目的情况自动改变某些菜单命令的有效状态,例如没有选中任何条目时, " 编辑条目 " 应处于不能选择的无效状态,它所对应的工具按钮也应无效;
3
.让 Schedule 能够象网络蚂蚁那样在最小化时隐藏自己的窗口,在任务栏的通知区域内放置一个图标,并设计相关的菜单;
4
.修改 Schedule 的用户界面,设计更好的图标和位图;
5
.修改添加和编辑事件条目的对话框,让用户能更直观地设置时间;
6
.设计一个启动画面,把某些选项保存到注册表之中;
7
.为 Schedule 增添打印功能;
… …
等等

CListCtrl 几点经验

每个List 控件都有一个CHeaderCtrl 。且它的ID0
CHeaderCtrl* pHeader =(CHeaderCtrl*)m_listCtrl.GetDlgItem(0);
即使List 控件非report 模式,Header 控件也存在,只是此时它的尺寸为0
可利用以下代码使得控件的第一列自适应大小:
m_listctrl.SetColumnWidth( 0, LVSCW_AUTOSIZE );
List
控件中的图标初始化时可如下设置:
m_listCtrl.InsertItem( LVIF_TEXT | LVIF_IMAGE, nRow, sItemText, 0, 0, nImage
, NULL);
在运行中需动态改变可调用SetItem() 函数.
m_listCtrl.SetItem( 0, 0, LVIF_IMAGE, NULL, nImage, 0, 0, 0 );
删去图标可将nImage 设置为-1

以下代码可将列表框的第一列限定大小:
BOOL CMyListCtrl::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
HD_NOTIFY *pHDN = (HD_NOTIFY*)lParam;
if((pHDN->hdr.code == HDN_BEGINTRACKW || pHDN->hdr.code == HDN_BEGIN
TRACKA)
&& pHDN->iItem == 0) // Prevent only first (col#
0) from resizing
{
*pResult = TRUE; // disable tracking
return TRUE; // Processed message
}
return CListCtrl::OnNotify(wParam, lParam, pResult);
}


选定cell
CListCtrl::OnClick(...)
{
int column;
CRect m_rect;
//the function below is provided in CListCtrl inPlace editing
int index = GetRowColumnIndex(point, &column);
if(index == -1)return;
int offset = 0;
for(int i = 0; i < column; i++)
offset += GetColumnWidth(i);
//Get the rectangle of the label and the icon
GetItemRect(index, &m_rect, LVIR_BOUNDS);
m_rect.left += offset + 4;
//Get the columnWidth of the selected column
m_rect.right = m_rect.left + GetColumnWidth(column);
Update(index);
CClientDC dc(this); //this is the pointer of the current view
dc.DrawFocusRect(m_rect);
}

Select NonFirst cell:

void CMyListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
CListCtrl::OnLButtonDown(nFlags, point);
int index;
point.x = 2;
if( ( index = HitTest( point, NULL )) != -1 )
{
SetItemState( index, LVIS_SELECTED | LVIS_FOCUSED ,
LVIS_SELECTED | LVIS_FOCUSED);
}
}


HitTestEx
的代码如下:
判断点击的是哪一列:
// HitTestEx - Determine the row index and column index for a point
// Returns - the row index or -1 if point is not over a row
// point - point to be tested.
// col - to hold the column index
int CMyListCtrl::HitTestEx(CPoint &point, int *col) const
{
int colnum = 0;
int row = HitTest( point, NULL );
if( col ) *col = 0;
// Make sure that the ListView is in LVS_REPORT
if( (GetWindowLong(m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT )
return row;
// Get the top and bottom row visible
row = GetTopIndex();
int bottom = row + GetCountPerPage();
if( bottom > GetItemCount() )
bottom = GetItemCount();
// Get the number of columns
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
int nColumnCount = pHeader->GetItemCount();
// Loop through the visible rows
for( ;row <=bottom;row++)
{
// Get bounding rect of item and check whether point falls in it.
CRect rect;
GetItemRect( row, &rect, LVIR_BOUNDS );
if( rect.PtInRect(point) )
{
// Now find the column
for( colnum = 0; colnum < nColumnCount; colnum++ )
{
int colwidth = GetColumnWidth(colnum);
if( point.x >= rect.left
&& point.x <= (rect.left + colwidth ) )
{
if( col ) *col = colnum;
return row;
}
rect.left += colwidth;
}
}
}
return -1;
}


选中一定范围内的Item
// SelItemRange - Selects/Deselect a range of items
// Returns - The number of new items selected
// bSelect - TRUE to select, FALSE to deselect
// nFirstItem - index of first item to select
// nLastItem - index of last item to select
int CMyListCtrl::SelItemRange(BOOL bSelect, int nFirstItem, int nLastItem)
{
// make sure nFirstItem and nLastItem are valid
if( nFirstItem >= GetItemCount() || nLastItem >= GetItemCount() )
return 0;
int nItemsSelected = 0;
int nFlags = bSelect ? 0 : LVNI_SELECTED;
int nItem = nFirstItem - 1;
while( (nItem = GetNextItem( nItem, nFlags )) >=0
&& nItem <= nLastItem )
{
nItemsSelected++;
SetItemState(nItem, bSelect ? LVIS_SELECTED : 0, LVIS_SELECT
ED );
}
return nItemsSelected;
}

SetHeaderBitmap:

static int _gnCols = 5;
static int _gnColSize[] =
{
18,21,22,18,380
};
static CString _gcsColLabel[] =
{
_T("x"),
_T("x"),
_T("x"),
_T("x"),
_T("Description:")
};
void CRightView::BuildColumns()
{
// Insert the columns into the list control
LV_COLUMN lvCol;
lvCol.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
for (int i = 0; i < _gnCols; ++i)
{
lvCol.iSubItem = i;
lvCol.pszText = (char*)(LPCTSTR)_gcsColLabel;
lvCol.cx = _gnColSize;
lvCol.fmt = LVCFMT_LEFT;
m_ListCtrl->InsertColumn(i, &lvCol);
}
for (int x = 0; x < _gnCols-1; x++)
SetHeaderBitmap(x, nHeaderBmps[x], HDF_STRING);
}
void CRightView::SetHeaderBitmap(int nCol, int nBitmap, DWORD dwRemove)
{
CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
HD_ITEM hdi;
hdi.mask = HDI_FORMAT;
pHeader->GetItem (nCol, &hdi);
hdi.mask = HDI_BITMAP | HDI_FORMAT;
hdi.fmt |= HDF_BITMAP;
hdi.hbm = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(nBitmap),IMAGE_BITMAP,0,0,LR_LOADMAP3DCOLORS);
if (dwRemove)
hdi.fmt &= ~dwRemove;
pHeader->SetItem (nCol, &hdi);
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics