📄 widget.c
字号:
// This widget has no siblings, so go to its parent. Since
// the parent has already been searched, the same sibling
// vs. parent decision must be made on this widget as well.
//
pTemp = pTemp->pParent;
}
}
}
}
//
// The widget could not be found.
//没有找到,返回0
return(0);
}
//*****************************************************************************
//
//! Handles widget messages.
//!
//! \param pWidget is a pointer to the widget.
//! \param ulMessage is the message to be processed.
//! \param ulParam1 is the first parameter to the message.
//! \param ulParam2 is the second parameter to the message.
//!
//! This function is a default handler for widget messages; it simply ignores
//! all messages sent to it. This is used as the message handler for the root
//! widget, and should be called by the message handler for other widgets when
//! they do not explicitly handle the provided message (in case new messages
//! are added that require some default but override-able processing).
//!
//! \return Always returns 0.
//默认的控件处理函数
//*****************************************************************************
long
WidgetDefaultMsgProc(tWidget *pWidget, unsigned long ulMessage,
unsigned long ulParam1, unsigned long ulParam2)
{
//
// Check the arguments.
//
ASSERT(pWidget);
//
// Return zero for all messages.
//
return(0);
}
//*****************************************************************************
//
//! Adds a widget to the widget tree.
//!
//! \param pParent is the parent for the widget. To add to the root of the tree
//! set this parameter to \b WIDGET_ROOT.
//! \param pWidget is the widget to add.
//!
//! This function adds a widget to the widget tree at the given position within
//! the tree. The widget will become the last child of its parent, and will
//! therefore be searched after the existing children.
//!
//! The added widget can be a full widget tree, allowing addition of an entire
//! heirarchy all at once (for example, adding an entire screen to the widget
//! tree all at once). In this case, it is the responsibility of the caller to
//! ensure that the pParent field of each widget in the added tree is correctly
//! set (in other words, only the widget pointed to by \e pWidget is updated to
//! properly reside in the tree).
//!
//! It is the responsibility of the caller to initialize the pNext and pChild
//! field of the added widget; either of these fields being non-zero results in
//! a pre-defined tree of widgets being added instead of a single one.
//!
//! \return None.
//为父控件添加子控件
//*****************************************************************************
void
WidgetAdd(tWidget *pParent, tWidget *pWidget)
{
//
// Check the arguments.
//
ASSERT(pParent);
ASSERT(pWidget);
//
// Make this widget be a child of its parent.
//先把子控件的父指针指向父控件
pWidget->pParent = pParent;
//
// See if this parent already has children.
//该父控件有子控件
if(pParent->pChild)
{
//
// Find the last child of this parent and also check that widget is not
// already present at this level of the tree.
//遍历查找其子控件中是否已经有了此子控件
for(pParent = pParent->pChild; pParent->pNext;
pParent = pParent->pNext)
{
//
// If we find this widget here already, just return. If we don't
// do this, we allow errant programs to add the same child twice
// resulting in looping on message processing.
//
if(pParent == pWidget)
{
return;
}
}
//
// We perform one final check to see if we are about to add the widget
// twice. We need this to catch the case of a single child which
// causes the previous loop to exit before performing the widget check.
//
if(pParent == pWidget)
{
return;
}
//
// Add this widget to the end of the list of children of this parent.
//没有该子控件,进行添加,并且为同层次的子控件的兄弟控件
pParent->pNext = pWidget;
}
else //没有子控件
{
//
// Make this widget be the first (and only) child of this parent.
//
pParent->pChild = pWidget;
}
}
//*****************************************************************************
//
//! Removes a widget from the widget tree.
//!
//! \param pWidget is the widget to be removed.
//!
//! This function removes a widget from the widget tree. The removed widget
//! can be a full widget tree, allowing removal of an entire heirarchy all at
//! once (for example, removing an entire screen from the widget tree).
//!
//! \return None.
//删除控件
//*****************************************************************************
void
WidgetRemove(tWidget *pWidget)
{
tWidget *pTemp;
//
// Check the argument.
//
ASSERT(pWidget);
//
// Make sure that the supplied widget is actually in the tree section
// owned by its parent and, hence, removeable.
//判读其是否为最高层的控件,以及该控件树中是否包含此空间
if(!pWidget->pParent || !WidgetIsInTree(pWidget->pParent, pWidget))
{
return;
}
//
// See if this widget is the first child of its parent.
//是否为父控件指向的第一个子控件。
if(pWidget->pParent->pChild == pWidget)
{
//
// Make the first child of this widgets parent be this widget's
// sibling.
//是第一个子控件,应将其父控件的子控件指向其兄弟控件
pWidget->pParent->pChild = pWidget->pNext;
}
else
{
//
// Find the sibling directly before this widget.
//查找到需要删除控件的前一个兄弟控件
for(pTemp = pWidget->pParent->pChild; pTemp->pNext != pWidget;
pTemp = pTemp->pNext)
{
}
//
// Make the previous sibling point to the next sibling, removing this
// widget from the sibling chain.
//进行删除
pTemp->pNext = pWidget->pNext;
}
//
// Check to see if the widget which currently owns the pointer has just
// been removed and, if so, clear the pointer focus.
//
if(g_pPointerWidget && !WidgetIsInTree(&g_sRoot, g_pPointerWidget))
{
g_pPointerWidget = 0;
}
//
// Clear the next pointer of the widget.
//
pWidget->pNext = 0;
}
//*****************************************************************************
//
//! Sends a message to a widget tree via a pre-order, depth-first search.
//!
//! \param pWidget is a pointer to the widget tree.
//! \param ulMessage is the message to send.
//! \param ulParam1 is the first parameter to the message.
//! \param ulParam2 is the second parameter to the message.
//! \param bStopOnSuccess is true if the search should be stopped when the
//! first widget is found that returns success in response to the message.
//!
//! This function performs a pre-order, depth-first search of the widget tree,
//! sending a message to each widget encountered. In a depth-first search, the
//! children of a widget are searched before its siblings (preferring to go
//! deeper into the tree, hence the name depth-first). A pre-order search
//! means that the message is sent to a widget before any of its children are
//! searched.
//!
//! An example use of the pre-order search is for paint messages; the larger
//! enclosing widgets should be drawn on the screen before the smaller widgets
//! that reside within the parent widget (otherwise, the children would be
//! overwritten by the parent).
//!
//! \return Returns 0 if \e bStopOnSuccess is false or no widget returned
//! success in response to the message, or the value returned by the first
//! widget to successfully process the message.
//先序传输,深度优先
//在遍历过程中先把遍历到的节点进行信息传输,并且直到最底层。
//然后进行对应的兄弟节点的信息传输,操作
//
//
//*****************************************************************************
unsigned long
WidgetMessageSendPreOrder(tWidget *pWidget, unsigned long ulMessage,
unsigned long ulParam1, unsigned long ulParam2,
unsigned long bStopOnSuccess)
{
unsigned long ulRet;
tWidget *pTemp;
//
// Check the arguments.
//
ASSERT(pWidget);
//
// Send the message to the initial widget and return if it succeeded and
// the search should stop on success.
//
ulRet = pWidget->pfnMsgProc(pWidget, ulMessage, ulParam1, ulParam2);
if((ulRet != 0) && bStopOnSuccess)
{
return(ulRet);
}
//
// Return if the widget does not have any children.
//
if(!pWidget->pChild)
{
return(0);
}
//
// Loop through the tree under the widget until every widget is searched.
//
for(pTemp = pWidget->pChild; pTemp != pWidget; )
{
//
// Send the message to this widget and return if it succeeded and the
// search should stop on success.
//
ulRet = pTemp->pfnMsgProc(pTemp, ulMessage, ulParam1, ulParam2);
if((ulRet != 0) && bStopOnSuccess)
{
return(ulRet);
}
//
// Find the next widget to examine. If this widget has a child, then
// that is the next widget to examine.
//
if(pTemp->pChild)
{
pTemp = pTemp->pChild;
}
//
// This widget does not have a child, so either a sibling or a parent
// must be checked. When moving back to the parent, another move must
// be performed as well to avoid getting stuck in a loop (since the
// parent's children have already been searched).
//
else
{
//
// Loop until returning to the starting widget. This loop will be
// explicitly broken out of if an intervening widget is encountered
// that has not be searched.
//
while(pTemp != pWidget)
{
//
// See if this widget has a sibling.
//
if(pTemp->pNext)
{
//
// Visit the sibling of this widget.
//
pTemp = pTemp->pNext;
//
// Since this widget has not been searched yet, break out
// of the controlling loop.
//
break;
}
else
{
//
// This widget has no siblings, so go to its parent. Since
// the parent has already been searched, the same sibling
// vs. parent decision must be made on this widget as well.
//
pTemp = pTemp->pParent;
}
}
}
}
//
// No widget returned success for the message, or bStopOnSuccess was zero,
// so return zero.
//
return(0);
}
//*****************************************************************************
//
//! Sends a message to a widget tree via a post-order, depth-first search.
//!
//! \param pWidget is a pointer to the widget tree; if this is zero then the
//! root of the widget tree willb e used.
//! \param ulMessage is the message to send.
//! \param ulParam1 is the first parameter to the message.
//! \param ulParam2 is the second parameter to the message.
//! \param bStopOnSuccess is true if the search should be stopped when the
//! first widget is found that returns success in response to the message.
//!
//! This function performs a post-order, depth-first search of the widget tree,
//! sending a message to each widget encountered. In a depth-first search, the
//! children of a widget are searched before its sibling (preferring to go
//! deeper into the tree, hence the name depth-first). A post-order search
//! means that the message is sent to a widget after all of its children are
//! searched.
//!
//! An example use of the post-order search is for pointer-related messages;
//! those messages should be delivered to the lowest widget in the tree before
//! its parents (in other words, the widget deepest in the tree that has a hit
//! should get the message, not the higher up widgets that also include the hit
//! location).
//!
//! Special handling is performed for pointer-related messages. The widget
//! that accepts \b #WIDGET_MSG_PTR_DOWN is remembered and subsequent
//! \b #WIDGET_MSG_PTR_MOVE and \b #WIDGET_MSG_PTR_UP messages are sent
//! directly to that widget.
//!
//! \return Returns 0 if \e bStopOnSuccess is false or no widget returned
//! success in response to the message, or the value returned by the first
//! widget to successfully process the message.
//后序传输,深度优先。
//当进行到最底层后,开始依次进行信息传输
//在遍历过程中不进行信息传输。
//
//
//
//*****************************************************************************
unsigned long
WidgetMessageSendPostOrder(tWidget *pWidget, unsigned long ulMessage,
unsigned long ulParam1, unsigned long ulParam2,
unsigned long bStopOnSuccess)
{
unsigned long ulRet;
tWidget *pTemp;
//
// Check the arguments.
//
ASSERT(pWidget);
//
// See if this is a pointer move or up message.
//
if((ulMessage == WIDGET_MSG_PTR_MOVE) || (ulMessage == WIDGET_MSG_PTR_UP))
{
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -