mirror of https://github.com/lianthony/NT4.0
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.
389 lines
11 KiB
389 lines
11 KiB
/****************************** Module Header ******************************\
|
|
* Module Name: class.c
|
|
*
|
|
* Copyright (c) 1985-91, Microsoft Corporation
|
|
*
|
|
* This module contains RegisterClass and the related window class management
|
|
* functions.
|
|
*
|
|
* History:
|
|
* 12-20-94 FritzS
|
|
*
|
|
\***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
BOOL VisWindow(DWORD);
|
|
|
|
|
|
/***************************************************************************\
|
|
* xxxSetClassIconEnum
|
|
*
|
|
*
|
|
\***************************************************************************/
|
|
|
|
BOOL xxxSetClassIconEnum(
|
|
PWND pwnd,
|
|
LPARAM lParam)
|
|
{
|
|
if (pwnd->pcls == (PCLS)lParam) {
|
|
/*
|
|
* If the window doesn't have a small icon or it comes from
|
|
* WM_QUERYDRAGICON, redraw the title. In the WM_QUERYDRAGICON
|
|
* case, get rid of the small icon so redrawing the title will
|
|
* create it if necessary.
|
|
*/
|
|
if (TestWF(pwnd, WFSMQUERYDRAGICON))
|
|
DestroyWindowSmIcon(pwnd);
|
|
|
|
if (!_GetProp(pwnd, MAKEINTATOM(gpsi->atomIconSmProp),PROPF_INTERNAL))
|
|
xxxRedrawTitle(pwnd, DC_ICON);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* SetClassIcon
|
|
*
|
|
* Changes the big/small icon of a class. Called from SetClassWord().
|
|
*
|
|
\***************************************************************************/
|
|
|
|
PCURSOR xxxSetClassIcon(
|
|
PWND pwnd,
|
|
PCLS pcls,
|
|
PCURSOR pCursor,
|
|
int gcw)
|
|
{
|
|
PTHREADINFO pti = PtiCurrent();
|
|
PCURSOR pCursorOld;
|
|
TL tlpwndChild;
|
|
BOOL fRedraw;
|
|
|
|
/*
|
|
* Save old icon
|
|
*/
|
|
pCursorOld = ((gcw == GCL_HICON) ? pcls->spicn : pcls->spicnSm);
|
|
|
|
if (pCursorOld != pCursor) {
|
|
|
|
fRedraw = TRUE;
|
|
|
|
/*
|
|
* Set new icon
|
|
*/
|
|
if (gcw == GCL_HICON) {
|
|
|
|
/*
|
|
* Destroy private cached small icon first.
|
|
*/
|
|
if (pcls->spicnSm && !DestroyClassSmIcon(pcls))
|
|
fRedraw = FALSE;
|
|
|
|
Lock(&(pcls->spicn), pCursor);
|
|
|
|
} else {
|
|
|
|
/*
|
|
* We don't allow apps to see the small icons we create from
|
|
* their big icons. They can see their own. Saves memory
|
|
* leak problems and is easier.
|
|
*/
|
|
if (TestCF2(pcls, CFCACHEDSMICON)) {
|
|
DestroyClassSmIcon(pcls);
|
|
pCursorOld = NULL;
|
|
}
|
|
|
|
Lock(&(pcls->spicnSm), pCursor);
|
|
}
|
|
|
|
if (pcls->spicn && !pcls->spicnSm)
|
|
xxxCreateClassSmIcon(pcls);
|
|
|
|
if (fRedraw) {
|
|
|
|
if (pcls->cWndReferenceCount > 1) {
|
|
ThreadLock(pti->rpdesk->pDeskInfo->spwnd->spwndChild, &tlpwndChild);
|
|
xxxInternalEnumWindow(pti->rpdesk->pDeskInfo->spwnd->spwndChild,
|
|
(WNDENUMPROC_PWND)xxxSetClassIconEnum,
|
|
(LONG)pcls,
|
|
BWL_ENUMLIST);
|
|
ThreadUnlock(&tlpwndChild);
|
|
} else {
|
|
xxxSetClassIconEnum(pwnd, (LONG)pcls);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(pCursorOld);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* DestroyClassSmIcon()
|
|
*
|
|
* Destroys the small icon of a class if we've created a cached one.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
BOOL DestroyClassSmIcon(
|
|
PCLS pcls)
|
|
{
|
|
|
|
/*
|
|
* If we don't have a cached icon, then no work.
|
|
*/
|
|
if (TestCF2(pcls, CFCACHEDSMICON)) {
|
|
if (pcls->spicnSm) {
|
|
_DestroyCursor(pcls->spicnSm, CURSOR_ALWAYSDESTROY);
|
|
Unlock(&pcls->spicnSm);
|
|
}
|
|
ClrCF2(pcls, CFCACHEDSMICON);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* xxxCreateClassSmIcon
|
|
*
|
|
* Creates a cached class small icon from a class big icon.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
VOID xxxCreateClassSmIcon(
|
|
PCLS pcls)
|
|
{
|
|
PCURSOR pcur;
|
|
|
|
UserAssert(pcls->cWndReferenceCount > 0);
|
|
UserAssert(pcls->spicn);
|
|
UserAssert(!pcls->spicnSm);
|
|
|
|
pcur = xxxClientCopyImage(PtoH(pcls->spicn),
|
|
pcls->spicn->rt == (WORD)RT_ICON ? IMAGE_ICON : IMAGE_CURSOR,
|
|
SYSMET(CXSMICON),
|
|
SYSMET(CYSMICON),
|
|
LR_DEFAULTCOLOR | LR_COPYFROMRESOURCE);
|
|
|
|
Lock(&pcls->spicnSm, pcur);
|
|
if (pcls->spicnSm)
|
|
SetCF2(pcls, CFCACHEDSMICON);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* SetWindowStyle
|
|
*
|
|
* Changes the style bits of a window. Called from SetWindowLong(). This
|
|
* sends two messages, a changing and a changed. Upon receipt of a
|
|
* WM_STYLECHANGING message, a window can muck with the style bits for
|
|
* validation purposes. The WM_STYLECHANGED message is simply after the
|
|
* fact.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
LONG xxxSetWindowStyle(
|
|
PWND pwnd,
|
|
int gwl,
|
|
DWORD styleNew)
|
|
{
|
|
STYLESTRUCT sty;
|
|
BOOL fWasChild;
|
|
BOOL fIsChild;
|
|
|
|
/*
|
|
* HACK-O-RAMA
|
|
* A STYLESTRUCT currently has just one field: a DWORD for the style.
|
|
* Therefore, conveniently, we can pass a pointer into the stack for
|
|
* LPARAM. But, if we add stuff, we'll have to change this.
|
|
*/
|
|
sty.styleOld = ((gwl == GWL_STYLE) ? pwnd->style : pwnd->ExStyle);
|
|
sty.styleNew = styleNew;
|
|
|
|
/*
|
|
* Note that we don't do validation before _and_ after. It is sufficient
|
|
* to do our stuff at the end.
|
|
*/
|
|
|
|
/*
|
|
* We break Quicken 2.0 if we send the messages. That's why we version
|
|
* switch them.
|
|
*/
|
|
|
|
/*
|
|
* Send a WM_STYLECHANGING message to the window, so it can muck with
|
|
* the style bits. Like validate some stuff.
|
|
*/
|
|
if (TestWF(pwnd, WFWIN40COMPAT)) {
|
|
xxxSendMessage(pwnd, WM_STYLECHANGING, gwl, (LPARAM)(LPSTYLESTRUCT)&sty);
|
|
}
|
|
|
|
/*
|
|
* Now do our own validation.
|
|
*/
|
|
if (gwl == GWL_STYLE) {
|
|
|
|
BOOL fWasVisWindow;
|
|
|
|
/*
|
|
* If this is an edit control that has ES_PASSWORD set and
|
|
* the caller does not own it and is trying to reset it,
|
|
* fail the call.
|
|
*/
|
|
if ((PpiCurrent() != GETPTI(pwnd)->ppi) &&
|
|
(GETFNID(pwnd) == FNID_EDIT) &&
|
|
(sty.styleOld & ES_PASSWORD) &&
|
|
!(sty.styleNew & ES_PASSWORD)) {
|
|
RIPERR0(ERROR_ACCESS_DENIED,
|
|
RIP_WARNING,
|
|
"Access denied in xxxSetWindowStyle");
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Listbox ownerdraw style check was moved to the client side (client\ntstubs.c) */
|
|
|
|
/*
|
|
* Do proper validation on style bits
|
|
*/
|
|
if (pwnd->spwndParent == PWNDDESKTOP(pwnd))
|
|
sty.styleNew |= WS_CLIPSIBLINGS;
|
|
|
|
/*
|
|
* If the clipping-ness is changing, invalidate the dc cache.
|
|
*/
|
|
if ((sty.styleNew & (WS_CLIPCHILDREN | WS_CLIPSIBLINGS)) !=
|
|
(sty.styleOld & (WS_CLIPCHILDREN | WS_CLIPSIBLINGS))) {
|
|
|
|
InvalidateDCCache(pwnd, IDC_DEFAULT);
|
|
}
|
|
|
|
/*
|
|
* This breaks all Paradox dialogs 1.0-5.0 that have combos. They
|
|
* enumerate all child windows, add on minimized, then sit in a peek
|
|
* loop. After that they enumerate all child windows and remove
|
|
* WS_MINIMIZE--except the code below won't let them.
|
|
*
|
|
* Result is weird painting and an inability to use the dialog any
|
|
* more short of dismissing it
|
|
*
|
|
* Temp fix: Check for child window first.
|
|
*/
|
|
|
|
/*
|
|
* if this window is REALLY minimized (minimized bit is set and caption
|
|
* present bit is removed), then don't allow app to remove the minimize
|
|
* bit -- this fixes FoxBlow's attempt at being the OS -- jeffbog
|
|
*/
|
|
if (!TestWF(pwnd, WFCHILD) &&
|
|
TestWF(pwnd, WFMINIMIZED) &&
|
|
!TestWF(pwnd, WFCPRESENT) &&
|
|
!(sty.styleNew & WS_MINIMIZE)) {
|
|
|
|
sty.styleNew |= WS_MINIMIZE;
|
|
}
|
|
|
|
/*
|
|
* If we're changing the child bit, deal with spmenu appropriately.
|
|
* If we're turning into a child, change spmenu to an id. If we're
|
|
* turning into a top level window, turn spmenu into a menu.
|
|
*/
|
|
fWasChild = TestwndChild(pwnd);
|
|
|
|
pwnd->style = sty.styleNew;
|
|
|
|
fIsChild = TestwndChild(pwnd);
|
|
|
|
/*
|
|
* If we turned into a top level window, change spmenu to NULL.
|
|
* If we turned into a child from a top level window, unlock spmenu.
|
|
*/
|
|
if (fWasChild && !fIsChild)
|
|
pwnd->spmenu = NULL;
|
|
|
|
if (!fWasChild && fIsChild) {
|
|
ClrWF(pwnd, WFMPRESENT);
|
|
Unlock(&pwnd->spmenu);
|
|
}
|
|
|
|
/*
|
|
* If the visible, child, or minimized style is changing,
|
|
* then update the cVisWindows count
|
|
*/
|
|
fWasVisWindow = VisWindow(sty.styleOld);
|
|
if (fWasVisWindow != VisWindow(sty.styleNew))
|
|
{
|
|
// IncDecVisWindows(pwnd, !fWasVisWindow);
|
|
if (fWasVisWindow)
|
|
DecVisWindows(pwnd);
|
|
else
|
|
IncVisWindows(pwnd);
|
|
}
|
|
} else {
|
|
|
|
/*
|
|
* Is someone trying to toggle the WS_EX_TOPMOST style bit?
|
|
*/
|
|
if ((sty.styleOld & WS_EX_TOPMOST) != (sty.styleNew & WS_EX_TOPMOST)) {
|
|
|
|
#ifdef DEBUG
|
|
/*
|
|
* Rip in debug about this
|
|
*/
|
|
RIPMSG0(RIP_WARNING, "Can't change WS_EX_TOPMOST with SetWindowLong");
|
|
#endif
|
|
|
|
/*
|
|
* BACKWARDS COMPATIBILITY HACK
|
|
* If stuff is getting stored in the high word, then it must be
|
|
* Lotus 123-W sticking a FAR pointer in this field. So don't
|
|
* modify it.
|
|
*/
|
|
if (TestWF(pwnd, WFWIN40COMPAT) || !HIWORD(sty.styleNew)) {
|
|
|
|
/*
|
|
* Don't let the bit be flipped
|
|
*/
|
|
sty.styleNew &= ~WS_EX_TOPMOST;
|
|
sty.styleNew |= (sty.styleOld & WS_EX_TOPMOST);
|
|
}
|
|
}
|
|
|
|
|
|
pwnd->ExStyle = sty.styleNew;
|
|
}
|
|
|
|
/*
|
|
* See if we still need the 3D edge since the window styles changed.
|
|
*/
|
|
if (NeedsWindowEdge(pwnd->style, pwnd->ExStyle, TestWF(pwnd, WFWIN40COMPAT)))
|
|
SetWF(pwnd, WEFWINDOWEDGE);
|
|
else
|
|
ClrWF(pwnd, WEFWINDOWEDGE);
|
|
|
|
/*
|
|
* Send a WM_STYLECHANGED message
|
|
*/
|
|
if (TestWF(pwnd, WFWIN40COMPAT))
|
|
xxxSendMessage(pwnd, WM_STYLECHANGED, gwl, (LPARAM)(LPSTYLESTRUCT)&sty);
|
|
|
|
return(sty.styleOld);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* VisWindow
|
|
*
|
|
* Based on style, determines if this is considered to be "visible" by
|
|
* queue foreground styles.
|
|
*
|
|
\***************************************************************************/
|
|
|
|
BOOL VisWindow(
|
|
DWORD style)
|
|
{
|
|
return(((style & (WS_POPUP | WS_CHILD)) != WS_CHILD) &&
|
|
!(style & WS_MINIMIZE) &&
|
|
(style & WS_VISIBLE));
|
|
}
|