Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

275 lines
9.3 KiB

/**************************** Module Header ********************************\
* Module Name: help.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* Help function
*
* History:
* 04-15-91 JimA Ported.
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
DWORD _GetWindowContextHelpId(PWND pWnd)
{
return (DWORD)(ULONG_PTR)_GetProp(pWnd, MAKEINTATOM(gpsi->atomContextHelpIdProp),
PROPF_INTERNAL);
}
BOOL _SetWindowContextHelpId(PWND pWnd, DWORD dwContextId)
{
//If dwContextId is NULL, then this implies that the caller wants to
// remove the dwContextId associated with this Window.
if(dwContextId == 0) {
InternalRemoveProp(pWnd, MAKEINTATOM(gpsi->atomContextHelpIdProp),
PROPF_INTERNAL);
return(TRUE);
}
return (InternalSetProp(pWnd, MAKEINTATOM(gpsi->atomContextHelpIdProp),
(HANDLE)LongToHandle( dwContextId ), PROPF_INTERNAL | PROPF_NOPOOL));
}
/***************************************************************************\
* SendHelpMessage
*
*
\***************************************************************************/
void xxxSendHelpMessage(
PWND pwnd,
int iType,
int iCtrlId,
HANDLE hItemHandle,
DWORD dwContextId)
{
HELPINFO HelpInfo;
long lValue;
CheckLock(pwnd);
HelpInfo.cbSize = sizeof(HELPINFO);
HelpInfo.iContextType = iType;
HelpInfo.iCtrlId = iCtrlId;
HelpInfo.hItemHandle = hItemHandle;
HelpInfo.dwContextId = dwContextId;
lValue = _GetMessagePos();
HelpInfo.MousePos.x = GET_X_LPARAM(lValue);
HelpInfo.MousePos.y = GET_Y_LPARAM(lValue);
xxxSendMessage(pwnd, WM_HELP, 0, (LPARAM)(LPHELPINFO)&HelpInfo);
}
/*
* Modal loop for when the user has selected the help icon from the titlebar
*
*/
VOID xxxHelpLoop(PWND pwnd)
{
HWND hwndChild;
PWND pwndChild;
PWND pwndControl;
MSG msg;
RECT rc;
int cBorders;
PTHREADINFO ptiCurrent = PtiCurrent();
DLGENUMDATA DlgEnumData;
TL tlpwndChild;
CheckLock(pwnd);
UserAssert(IsWinEventNotifyDeferredOK());
xxxWindowEvent(EVENT_SYSTEM_CONTEXTHELPSTART, pwnd, OBJID_WINDOW, INDEXID_CONTAINER, 0);
zzzSetCursor(SYSCUR(HELP));
xxxCapture(ptiCurrent, pwnd, SCREEN_CAPTURE);
cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE);
CopyInflateRect(&rc, &pwnd->rcWindow, -cBorders * SYSMET(CXBORDER), -cBorders * SYSMET(CYBORDER));
while (ptiCurrent->pq->spwndCapture == pwnd) {
if (!xxxPeekMessage(&msg, NULL, 0, 0, PM_NOYIELD | PM_NOREMOVE)) {
xxxWaitMessage();
continue;
}
if (msg.message == WM_NCLBUTTONDOWN) {
break;
} else if (msg.message == WM_LBUTTONDOWN) {
/*
* If user clicked outside of window client, bail out now.
*/
if (!PtInRect(&rc, msg.pt))
break;
/*
* WindowHitTest() won't return a static control's handle
*/
hwndChild = xxxWindowHitTest(pwnd, msg.pt, NULL, 0);
pwndChild = ValidateHwnd( hwndChild );
ThreadLock(pwndChild, &tlpwndChild);
if (pwndChild && FIsParentDude(pwndChild))
{
/*
* If this is a dialog class, then one of three things has
* happened:
*
* o This is a static text control
* o This is the background of the dialog box.
*
* What we do is enumerate the child windows and see if
* any of them contain the current cursor point. If they do,
* change our window handle and continue on. Otherwise,
* return doing nothing -- we don't want context-sensitive
* help for a dialog background.
*
* If this is a group box, then we might have clicked on a
* disabled control, so we enumerate child windows to see
* if we get another control.
*/
/*
* We're enumerating a dialog's children. So, if we don't
* find any matches, hwndChild will be NULL and the check
* below will drop out.
*/
DlgEnumData.pwndDialog = pwndChild;
DlgEnumData.pwndControl = NULL;
DlgEnumData.ptCurHelp = msg.pt;
xxxInternalEnumWindow(pwndChild, EnumPwndDlgChildProc, (LPARAM)&DlgEnumData, BWL_ENUMCHILDREN);
pwndControl = DlgEnumData.pwndControl;
} else {
pwndControl = pwndChild;
}
/*
* If we click on nothing, just exit.
*/
if (pwndControl == pwnd) {
pwndControl = NULL;
}
/*
* HACK ALERT (Visual Basic 4.0) - they have their own non-window
* based controls that draw directly on the main dialog. In order
* to provide help for these controls, we pass along the WM_HELP
* message iff the main dialog has a context id assigned.
*
* If the top level window has its own context help ID,
* then pass it in the context help message.
*/
if (!pwndControl) {
if (_GetProp(pwnd, MAKEINTATOM(gpsi->atomContextHelpIdProp), TRUE))
pwndControl = pwnd;
}
if (pwndControl) {
PWND pwndSend;
int id;
TL tlpwndSend;
TL tlpwndControl;
ThreadLockAlways(pwndControl, &tlpwndControl);
zzzSetCursor(SYSCUR(ARROW));
xxxReleaseCapture();
xxxRedrawTitle(pwnd, DC_BUTTONS);
ClrWF(pwnd, WFHELPBUTTONDOWN);
xxxGetMessage(&msg, NULL, 0, 0);
xxxWindowEvent(EVENT_OBJECT_STATECHANGE, pwnd, OBJID_TITLEBAR,
INDEX_TITLEBAR_HELPBUTTON, FALSE);
xxxWindowEvent(EVENT_SYSTEM_CONTEXTHELPEND, pwnd, OBJID_WINDOW,
INDEXID_CONTAINER, FALSE);
/*
* Determine the ID of the control
* We used to always sign extend, but Win98 doesn't do that
* so we only sign extend 0xffff. MCostea #218711
*/
if (TestwndChild(pwndControl)) {
id = PTR_TO_ID(pwndControl->spmenu);
if (id == 0xffff) {
id = -1;
}
} else {
id = -1;
}
/*
* Disabled controls and static controls won't pass this
* on to their parent, so instead, we send the message to
* their parent.
*/
if (TestWF(pwndControl, WFDISABLED)) {
PWND pwndParent = _GetParent(pwndControl);
if (!pwndParent)
{
ThreadUnlock( &tlpwndControl );
ThreadUnlock( &tlpwndChild );
return;
}
pwndSend = pwndParent;
} else {
pwndSend = pwndControl;
}
ThreadLockAlways(pwndSend, &tlpwndSend);
xxxSendHelpMessage( pwndSend, HELPINFO_WINDOW, id,
(HANDLE)HWq(pwndControl), GetContextHelpId(pwndControl));
ThreadUnlock(&tlpwndSend);
ThreadUnlock(&tlpwndControl);
ThreadUnlock(&tlpwndChild);
return;
}
ThreadUnlock(&tlpwndChild);
break;
}
else if ((msg.message == WM_RBUTTONDOWN) ||
(msg.message == WM_MBUTTONDOWN) ||
(msg.message == WM_XBUTTONDOWN)) {
/*
* fix bug 29852; break the loop for right and middle buttons
* and pass along the messages to the control
*/
break;
}
else if (msg.message == WM_MOUSEMOVE) {
if (PtInRect(&rc, msg.pt))
zzzSetCursor(SYSCUR(HELP));
else
zzzSetCursor(SYSCUR(ARROW));
}
else if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE)
{
xxxGetMessage( &msg, NULL, 0, 0 );
break;
}
xxxGetMessage(&msg, NULL, 0, 0);
xxxTranslateMessage(&msg, 0);
xxxDispatchMessage(&msg);
}
xxxReleaseCapture();
zzzSetCursor(SYSCUR(ARROW));
xxxRedrawTitle(pwnd, DC_BUTTONS);
ClrWF(pwnd, WFHELPBUTTONDOWN);
xxxWindowEvent(EVENT_OBJECT_STATECHANGE, pwnd, OBJID_TITLEBAR,
INDEX_TITLEBAR_HELPBUTTON, 0);
xxxWindowEvent(EVENT_SYSTEM_CONTEXTHELPEND, pwnd, OBJID_WINDOW,
INDEXID_CONTAINER, 0);
}