前简介
我用嵌入式VC + + 3.0,和2002年掌上电脑编写代码,因为它是在康柏iPAQ实施。您的里程可能会有所不同。简介
您知道它是如何。你screamin"以来,像一个疯狂的疯子(好了,所以这种情况很少发生与CE)编码,并与世界所有。然后,它发生。一个销售纳粹(或者更糟,否则联合国参与管理型)坚持在门头,说的东西,不仅会影响您的一天,但日程安排以及。在我的情况又是这样的:问题
"嘿约翰,对等,如对话框,当我打电话的键盘,它掩盖了现场我输入的数据。你能做些什么?quot;
的灵魂,我的好脾气,甚至脾气,我愉快地答复"是的,你刻着'白痴。我可以放弃我在做什么,现在和权利上it.quot;因此,我坐在。几番思索。经过一个星期的试验和错误,我终于想出了的东西。它仍然是一个有点古怪的(在这篇文章的末尾中描述的怪癖),但它几乎工程,我想它的方式,我以为我共享的财富,比如它。如何做到这一点
如果您尚未创建的CPropertyPage派生一个类。这isnbsp;必不可少的,如果你希望得到在一个合理的时间内做了什么。之后,在这里我们会做简而言之的:创建动态的滚动条。这可防止身体上放置所需的属性页模板,NBSP实际滚动;它让我们的scrollbarnbsp;比应用程序的工作室薄允许。覆盖的OnInitDialog。覆盖OnVScroll。检测时显示的SIP和解雇,并作出适当的反应。
我们先从基类的头文件的修改。首先,我们需要定义一个滚动的资源ID。在资源编辑器,我已经习惯在1000-10000范围内分配控件ID,当我需要的东西手动定义(像现在),我把它在64000-64100范围内。这就避免了与其他资源ID冲突。#define CE_DLGSCROLLBAR 64000
接下来,我们需要确保,我们的类的定义包括以下几行:{C}
接下来,我们需要添加一些代码基类的CPP文件。首先,我们要告诉基类,我们不需要一个滚动条,并不会自动滚屏设置一些默认值。顺便说一下,如果m_bAutoScroll是TRUE,propertypage将自动滚动到页面底部。我用这种方式是在文章的结尾附近。
因为我们将要使用Create()函数来构建的滚动,我们需要调用propertypage的析构函数的滚动的DestroyWindow()方法。CMyBasePropertyPage:: CMyBasePropertyPage()
{
if (IsWindow(m_ctrlScrollBar))
{
m_ctrlScrollBar.DestroyWindow();
}
}
现在,我们正在做的准备,这里的肉的代码。你应该有以下消息处理程序实施。对于WM_SETTINGCHANGE消息处理程序,你必须手动添加到您的代码,因为类向导不知道如何为你添加。还要注意,它liesnbsp;外AFX_MSG_MAP组。BEGIN_MESSAGE_MAP(CPtcPropertyPage, CPropertyPage)
//{{AFX_MSG_MAP(CPtcPropertyPage)
ON_WM_VSCROLL()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_SETTINGCHANGE, OnSettingChange)
END_MESSAGE_MAP()
现在,让我们添加初始化滚动条的功能。在这里,我们简单地创建滚动条,设置滚动范围和其他的滚动条的东西,然后隐藏它。
如果你想在SIP走时,他们改变到一个不同的属性页,使用类向导包括OnKillActive处理程序,像这样:BOOL CPtcPropertyPage::OnKillActive()
{
SHSipPreference(m_hWnd, SIP_FORCEDOWN);
return CPropertyPage::OnKillActive();
}
接下来,我们必须要能够自行处理滚动,当用户点击滚动条控制。由于我们采取这样一个小的滚动范围,我决定结合上一页(上下)的阵容(和下降。注意的项目之一是,为了获得新的滚动位置,你还必须处理的SB_ENDSCROLL消息(MSDN上的任何地方都没有提及这个小珍闻,我发现)。
另外一个有趣的项目是,尽管信息MSDN上的相反,调用SW_SCROLLCHILDREN标志设置ScrollWindowEx出现在2002年的PocketPC工作。诚然,MSDN说,它不工作在CE,这是,大家都知道, 不完全的PocketPC 2002年相同。//-------------------------------------------------------------------------
// Handle the WM_VSCROLL message
//-------------------------------------------------------------------------
void CMyBasePropertyPage::OnVScroll(UINT nSBCode,
UINT nPos, CScrollBar* pScrollBar)
{
if (pScrollBar == &m_ctrlScrollBar)
{
int nDelta = 0;
int nMaxPos = m_DlgClientRect.Height() - m_nCurHeight;
switch (nSBCode)
{
case SB_LINEDOWN:
case SB_PAGEDOWN:
if (m_nScrollPos >= nMaxPos)
{
return;
}
nDelta = min(max(nMaxPos / 2, 30), nMaxPos - m_nScrollPos);
break;
case SB_LINEUP:
case SB_PAGEUP:
if (m_nScrollPos <= 0)
{
return;
}
nDelta = -min(max(nMaxPos / 2, 30), m_nScrollPos);
break;
case SB_THUMBTRACK:
case SB_THUMBPOSITION:
nDelta = (int)nPos - m_nScrollPos;
break;
case SB_BOTTOM:
nDelta = 50;
break;
case SB_TOP:
if (m_nScrollPos <= 0)
{
return;
}
nDelta = -m_nScrollPos;
break;;
case SB_ENDSCROLL:
return;
default:
return;
}
m_nScrollPos += nDelta;
pScrollBar->SetScrollPos(m_nScrollPos, TRUE);
ScrollWindowEx(0, -nDelta, NULL, &m_DlgClientRect,
NULL, NULL, SW_SCROLLCHILDREN);
pScrollBar->MoveWindow(m_DlgClientRect.Width()-m_ScrollBarRect.Width(),
0, m_ScrollBarRect.Width(), m_ScrollBarRect.Height());
}
}
最后,我们必须处理WM_SETTINGCHANGE消息。 SIP状态变化时,此消息是发送到系统中。这个函数只是调用和投入的SIP的反应。当SIP显示,滚动条也显示,如有必要,propertypage是滚动的底部。当SIP被驳回,滚动条是隐藏的。
从派生类使用//------------------------------------------------------------------------
// We have to set up a custom handler for the
// WM_SETTINGCHANGE message because
// the CDialog class doesn't handle it by default.
//------------------------------------------------------------------------
LRESULT CMyBasePropertyPage::OnSettingChange(WPARAM wParam, LPARAM lParam)
{
if (m_bNeedScrollBar)
{
SIPINFO si;
memset(&si, 0, sizeof(si));
si.cbSize = sizeof(si);
if (SHSipInfo(SPI_GETSIPINFO, 0, &si, 0))
{
BOOL bShowScrollBar = ((si.fdwFlags & SIPF_ON) == SIPF_ON);
if (!bShowScrollBar)
{
if (m_nScrollPos > 0)
{
OnVScroll(SB_TOP, 0, &m_ctrlScrollBar);
}
m_ctrlScrollBar.ShowWindow(SW_HIDE);
}
else
{
// During testing, I discovered that the
// standard CE SIP is always the same
// height, no matter which SIP mode you're using.
// This means that if you're
// truly interested in performance
// (albeit a negligible gain), you can comment
// out this code so that the height of the
// scrollbar is always 142 pixels (as
// originally set when you called Create on the scrollbar).
CRect sipRect(si.rcSipRect);
CRect clientRect;
GetClientRect(&clientRect);
m_ctrlScrollBar.GetWindowRect(&m_ScrollBarRect);
m_ScrollBarRect.bottom =
m_ScrollBarRect.top + clientRect.Height();
m_ctrlScrollBar.MoveWindow(m_DlgClientRect.Width()-m_ScrollBarRect.Width(),
0, m_ScrollBarRect.Width(), m_ScrollBarRect.Height());
// show the scrollbar
m_ctrlScrollBar.ShowWindow(SW_SHOW);
if (m_bAutoScroll)
{
OnVScroll(SB_BOTTOM, 0, &m_ctrlScrollBar);
}
}
}
}
return 1L;
}
现在,我们有我们的基类,我们可以在派生类中使用滚动条。下面的代码是需要激活在基类中的滚动条的处理代码:CMyDerivedPage::OnInitDialog()
{
CMyBasePropertyPage::OnInitDialog();
initScrollBarSupport();
}
我的需要,我想有滚动条自动滚动,当一个特定组的控制的重点。要实现这个功能,我需要能够探测到任何页面上的控件获得焦点时,所以我的派生类中添加以下代码:
在头文件:
在CPP文件:
怪癖BEGIN_MESSAGE_MAP(CMyDerivedPage, CMyBasePropertyPage)
//{{AFX_MSG_MAP(CMyDerivedPage)
...
...
//}}AFX_MSG_MAP
ON_CONTROL_RANGE(EN_SETFOCUS, 0, 65535, OnEnSetFocus)
END_MESSAGE_MAP()
void CMyDerivedPage::OnEnSetFocus(UINT nID)
{
switch (nID)
{
case IDC_CONTROL1 :
case IDC_CONTROL2 :
case IDC_CONTROL3 :
m_bAutoScroll = TRUE;
break;
default :
m_bAutoScroll = FALSE;
break;
}
}
唯一古怪,我还没有想出是滚动到页面底部时。如果我使用的标签滚动,相当不走所有页面底部的方式。如果我点击向下箭头滚动按钮,滚动页面剩下的路。如果你想找出为什么发生这种情况,采取一捅,有一球,但让我知道。 :)|约翰西蒙斯/取缔程序员