mirror of
https://github.com/reactos/reactos.git
synced 2024-08-30 23:28:58 +00:00
Added user32 regression test from Wine.
svn path=/trunk/; revision=6694
This commit is contained in:
parent
7cc107f887
commit
56ec5a6edb
6
reactos/apps/tests/user32/.cvsignore
Normal file
6
reactos/apps/tests/user32/.cvsignore
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
*.o
|
||||||
|
*.d
|
||||||
|
*.exe
|
||||||
|
*.coff
|
||||||
|
*.sym
|
||||||
|
*.map
|
202
reactos/apps/tests/user32/class.c
Normal file
202
reactos/apps/tests/user32/class.c
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
/* Unit test suite for window classes.
|
||||||
|
*
|
||||||
|
* Copyright 2002 Mike McCormack
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "wine/test.h"
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "winreg.h"
|
||||||
|
#include "wingdi.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
|
||||||
|
#define NUMCLASSWORDS 4
|
||||||
|
|
||||||
|
LRESULT WINAPI ClassTest_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
return DefWindowProcW (hWnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* WinMain
|
||||||
|
*/
|
||||||
|
void ClassTest(HINSTANCE hInstance, BOOL global)
|
||||||
|
{
|
||||||
|
WNDCLASSW cls, wc;
|
||||||
|
WCHAR className[] = {'T','e','s','t','C','l','a','s','s',0};
|
||||||
|
WCHAR winName[] = {'W','i','n','C','l','a','s','s','T','e','s','t',0};
|
||||||
|
ATOM test_atom;
|
||||||
|
HWND hTestWnd;
|
||||||
|
DWORD i;
|
||||||
|
WCHAR str[20];
|
||||||
|
ATOM classatom;
|
||||||
|
|
||||||
|
cls.style = CS_HREDRAW | CS_VREDRAW | (global?CS_GLOBALCLASS:0);
|
||||||
|
cls.lpfnWndProc = ClassTest_WndProc;
|
||||||
|
cls.cbClsExtra = NUMCLASSWORDS*sizeof(DWORD);
|
||||||
|
cls.cbWndExtra = 12;
|
||||||
|
cls.hInstance = hInstance;
|
||||||
|
cls.hIcon = LoadIconW (0, (LPWSTR)IDI_APPLICATION);
|
||||||
|
cls.hCursor = LoadCursorW (0, (LPWSTR)IDC_ARROW);
|
||||||
|
cls.hbrBackground = GetStockObject (WHITE_BRUSH);
|
||||||
|
cls.lpszMenuName = 0;
|
||||||
|
cls.lpszClassName = className;
|
||||||
|
|
||||||
|
classatom=RegisterClassW(&cls);
|
||||||
|
if (!classatom && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
|
||||||
|
return;
|
||||||
|
ok(classatom, "failed to register class");
|
||||||
|
|
||||||
|
ok(!RegisterClassW (&cls),
|
||||||
|
"RegisterClass of the same class should fail for the second time");
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* these succeeds on Wine, but shouldn't cause any trouble ... */
|
||||||
|
ok(!GlobalFindAtomW(className),
|
||||||
|
"Found class as global atom");
|
||||||
|
|
||||||
|
ok(!FindAtomW(className),
|
||||||
|
"Found class as global atom");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Setup windows */
|
||||||
|
hTestWnd = CreateWindowW (className, winName,
|
||||||
|
WS_OVERLAPPEDWINDOW + WS_HSCROLL + WS_VSCROLL,
|
||||||
|
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0,
|
||||||
|
0, hInstance, 0);
|
||||||
|
|
||||||
|
ok(hTestWnd!=0, "Failed to create window");
|
||||||
|
|
||||||
|
/* test initial values of valid classwords */
|
||||||
|
for(i=0; i<NUMCLASSWORDS; i++)
|
||||||
|
{
|
||||||
|
SetLastError(0);
|
||||||
|
ok(!GetClassLongW(hTestWnd,i*sizeof (DWORD)),
|
||||||
|
"GetClassLongW initial value nonzero!");
|
||||||
|
ok(!GetLastError(),
|
||||||
|
"GetClassLongW failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* GetClassLongW(hTestWnd, NUMCLASSWORDS*sizeof(DWORD))
|
||||||
|
* does not fail on Win 98, though MSDN says it should
|
||||||
|
*/
|
||||||
|
SetLastError(0);
|
||||||
|
GetClassLongW(hTestWnd, NUMCLASSWORDS*sizeof(DWORD));
|
||||||
|
ok(GetLastError(),
|
||||||
|
"GetClassLongW() with invalid offset did not fail");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* set values of valid class words */
|
||||||
|
for(i=0; i<NUMCLASSWORDS; i++)
|
||||||
|
{
|
||||||
|
SetLastError(0);
|
||||||
|
ok(!SetClassLongW(hTestWnd,i*sizeof(DWORD),i+1),
|
||||||
|
"GetClassLongW(%ld) initial value nonzero!",i*sizeof(DWORD));
|
||||||
|
ok(!GetLastError(),
|
||||||
|
"SetClassLongW(%ld) failed!",i*sizeof(DWORD));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test values of valid classwords that we set */
|
||||||
|
for(i=0; i<NUMCLASSWORDS; i++)
|
||||||
|
{
|
||||||
|
SetLastError(0);
|
||||||
|
ok( (i+1) == GetClassLongW(hTestWnd,i*sizeof (DWORD)),
|
||||||
|
"GetClassLongW value doesn't match what was set!");
|
||||||
|
ok(!GetLastError(),
|
||||||
|
"GetClassLongW failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check GetClassName */
|
||||||
|
i = GetClassNameW(hTestWnd, str, sizeof(str));
|
||||||
|
ok(i == lstrlenW(className),
|
||||||
|
"GetClassName returned incorrect length");
|
||||||
|
ok(!lstrcmpW(className,str),
|
||||||
|
"GetClassName returned incorrect name for this window's class");
|
||||||
|
|
||||||
|
/* check GetClassInfo with our hInstance */
|
||||||
|
if((test_atom = GetClassInfoW(hInstance, str, &wc)))
|
||||||
|
{
|
||||||
|
ok(test_atom == classatom,
|
||||||
|
"class atom did not match");
|
||||||
|
ok(wc.cbClsExtra == cls.cbClsExtra,
|
||||||
|
"cbClsExtra did not match");
|
||||||
|
ok(wc.cbWndExtra == cls.cbWndExtra,
|
||||||
|
"cbWndExtra did not match");
|
||||||
|
ok(wc.hbrBackground == cls.hbrBackground,
|
||||||
|
"hbrBackground did not match");
|
||||||
|
ok(wc.hCursor== cls.hCursor,
|
||||||
|
"hCursor did not match");
|
||||||
|
ok(wc.hInstance== cls.hInstance,
|
||||||
|
"hInstance did not match");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ok(FALSE,"GetClassInfo (hinstance) failed!");
|
||||||
|
|
||||||
|
/* check GetClassInfo with zero hInstance */
|
||||||
|
if(global)
|
||||||
|
{
|
||||||
|
if((test_atom = GetClassInfoW(0, str, &wc)))
|
||||||
|
{
|
||||||
|
ok(test_atom == classatom,
|
||||||
|
"class atom did not match %x != %x", test_atom, classatom);
|
||||||
|
ok(wc.cbClsExtra == cls.cbClsExtra,
|
||||||
|
"cbClsExtra did not match %x!=%x",wc.cbClsExtra,cls.cbClsExtra);
|
||||||
|
ok(wc.cbWndExtra == cls.cbWndExtra,
|
||||||
|
"cbWndExtra did not match %x!=%x",wc.cbWndExtra,cls.cbWndExtra);
|
||||||
|
ok(wc.hbrBackground == cls.hbrBackground,
|
||||||
|
"hbrBackground did not match %p!=%p",wc.hbrBackground,cls.hbrBackground);
|
||||||
|
ok(wc.hCursor== cls.hCursor,
|
||||||
|
"hCursor did not match %p!=%p",wc.hCursor,cls.hCursor);
|
||||||
|
ok(!wc.hInstance,
|
||||||
|
"hInstance not zero for global class %p",wc.hInstance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ok(FALSE,"GetClassInfo (0) failed for global class!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok(!GetClassInfoW(0, str, &wc),
|
||||||
|
"GetClassInfo (0) succeeded for local class!");
|
||||||
|
}
|
||||||
|
|
||||||
|
ok(!UnregisterClassW(className, hInstance),
|
||||||
|
"Unregister class succeeded with window existing");
|
||||||
|
|
||||||
|
ok(DestroyWindow(hTestWnd),
|
||||||
|
"DestroyWindow() failed!");
|
||||||
|
|
||||||
|
ok(UnregisterClassW(className, hInstance),
|
||||||
|
"UnregisterClass() failed");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(class)
|
||||||
|
{
|
||||||
|
HANDLE hInstance = GetModuleHandleA( NULL );
|
||||||
|
|
||||||
|
ClassTest(hInstance,FALSE);
|
||||||
|
ClassTest(hInstance,TRUE);
|
||||||
|
}
|
357
reactos/apps/tests/user32/input.c
Normal file
357
reactos/apps/tests/user32/input.c
Normal file
|
@ -0,0 +1,357 @@
|
||||||
|
/* Test Key event to Key message translation
|
||||||
|
*
|
||||||
|
* Copyright 2003 Rein Klazes
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* test whether the right type of messages:
|
||||||
|
* WM_KEYUP/DOWN vs WM_SYSKEYUP/DOWN are sent in case of combined
|
||||||
|
* keystrokes.
|
||||||
|
*
|
||||||
|
* For instance <ALT>-X can be accompished by
|
||||||
|
* the sequence ALT-KEY-DOWN, X-KEY-DOWN, ALT-KEY-UP, X-KEY-UP
|
||||||
|
* but also X-KEY-DOWN, ALT-KEY-DOWN, X-KEY-UP, ALT-KEY-UP
|
||||||
|
* Whether a KEY or a SYSKEY message is sent is not always clear, it is
|
||||||
|
* also not the same in WINNT as in WIN9X */
|
||||||
|
|
||||||
|
/* NOTE that there will be test failures under WIN9X
|
||||||
|
* No applications are known to me that rely on this
|
||||||
|
* so I don't fix it */
|
||||||
|
|
||||||
|
/* TODO:
|
||||||
|
* 1. extend it to the wm_command and wm_syscommand notifications
|
||||||
|
* 2. add some more tests with special cases like dead keys or right (alt) key
|
||||||
|
* 3. there is some adapted code from input.c in here. Should really
|
||||||
|
* make that code exactly the same.
|
||||||
|
* 4. resolve the win9x case when there is a need or the testing frame work
|
||||||
|
* offers a nice way.
|
||||||
|
* 5. The test app creates a window, the user should not take the focus
|
||||||
|
* away during its short existence. I could do something to prevent that
|
||||||
|
* if it is a problem.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* for definitions of INPUT */
|
||||||
|
#define _WIN32_WINNT 0x401
|
||||||
|
|
||||||
|
#define NONAMELESSUNION
|
||||||
|
#define NONAMELESSSTRUCT
|
||||||
|
#include "wine/test.h"
|
||||||
|
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
|
||||||
|
typedef struct tagINPUT
|
||||||
|
{
|
||||||
|
DWORD type;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
MOUSEINPUT mi;
|
||||||
|
KEYBDINPUT ki;
|
||||||
|
HARDWAREINPUT hi;
|
||||||
|
} DUMMYUNIONNAME;
|
||||||
|
} INPUT, *PINPUT, *LPINPUT;
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
/* globals */
|
||||||
|
HWND hWndTest;
|
||||||
|
long timetag = 0x10000000;
|
||||||
|
|
||||||
|
#define MAXKEYEVENTS 6
|
||||||
|
#define MAXKEYMESSAGES MAXKEYEVENTS /* assuming a key event generates one
|
||||||
|
and only one message */
|
||||||
|
|
||||||
|
/* keyboard message names, sorted as their value */
|
||||||
|
static const char *MSGNAME[]={"WM_KEYDOWN", "WM_KEYUP", "WM_CHAR","WM_DEADCHAR",
|
||||||
|
"WM_SYSKEYDOWN", "WM_SYSKEYUP", "WM_SYSCHAR", "WM_SYSDEADCHAR" ,"WM_KEYLAST"};
|
||||||
|
|
||||||
|
/* keyevents, add more as needed */
|
||||||
|
typedef enum KEVtag
|
||||||
|
{ ALTDOWN = 1, ALTUP, XDOWN, XUP, SHIFTDOWN, SHIFTUP, CTRLDOWN, CTRLUP } KEV;
|
||||||
|
/* matching VK's */
|
||||||
|
int GETVKEY[]={0, VK_MENU, VK_MENU, 'X', 'X', VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL};
|
||||||
|
/* matching scan codes */
|
||||||
|
int GETSCAN[]={0, 0x38, 0x38, 0x2D, 0x2D, 0x2A, 0x2A, 0x1D, 0x1D };
|
||||||
|
/* matching updown events */
|
||||||
|
int GETUPDOWN[]={0, 0, KEYEVENTF_KEYUP, 0, KEYEVENTF_KEYUP, 0, KEYEVENTF_KEYUP, 0, KEYEVENTF_KEYUP};
|
||||||
|
/* matching descripts */
|
||||||
|
char *getdesc[]={"", "+alt","-alt","+X","-X","+shift","-shift","+ctrl","-ctrl"};
|
||||||
|
|
||||||
|
#define ADDTOINPUTS(kev) \
|
||||||
|
inputs[evtctr].type = INPUT_KEYBOARD; \
|
||||||
|
inputs[evtctr].u.ki.wVk = GETVKEY[ kev]; \
|
||||||
|
inputs[evtctr].u.ki.wScan = GETSCAN[ kev]; \
|
||||||
|
inputs[evtctr].u.ki.dwFlags = GETUPDOWN[ kev]; \
|
||||||
|
inputs[evtctr].u.ki.dwExtraInfo = 0; \
|
||||||
|
inputs[evtctr].u.ki.time = ++timetag; \
|
||||||
|
if( kev) evtctr++;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT message;
|
||||||
|
WPARAM wParam;
|
||||||
|
LPARAM lParam;
|
||||||
|
} KMSG;
|
||||||
|
|
||||||
|
/*******************************************
|
||||||
|
* add new test sets here
|
||||||
|
* the software will make all combinations of the
|
||||||
|
* keyevent defined here
|
||||||
|
*/
|
||||||
|
struct { int nrkev;
|
||||||
|
KEV keydwn[MAXKEYEVENTS];
|
||||||
|
KEV keyup[MAXKEYEVENTS];
|
||||||
|
} testkeyset[]= {
|
||||||
|
{ 2, { ALTDOWN, XDOWN }, { ALTUP, XUP}},
|
||||||
|
{ 3, { ALTDOWN, XDOWN , SHIFTDOWN}, { ALTUP, XUP, SHIFTUP}},
|
||||||
|
{ 3, { ALTDOWN, XDOWN , CTRLDOWN}, { ALTUP, XUP, CTRLUP}},
|
||||||
|
{ 3, { SHIFTDOWN, XDOWN , CTRLDOWN}, { SHIFTUP, XUP, CTRLUP}},
|
||||||
|
{ 0 } /* mark the end */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**********************adapted from input.c **********************************/
|
||||||
|
|
||||||
|
BYTE InputKeyStateTable[256];
|
||||||
|
BYTE AsyncKeyStateTable[256];
|
||||||
|
BYTE TrackSysKey = 0; /* determine whether ALT key up will cause a WM_SYSKEYUP
|
||||||
|
or a WM_KEYUP message */
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned long count : 16;
|
||||||
|
unsigned long code : 8;
|
||||||
|
unsigned long extended : 1;
|
||||||
|
unsigned long unused : 2;
|
||||||
|
unsigned long win_internal : 2;
|
||||||
|
unsigned long context : 1;
|
||||||
|
unsigned long previous : 1;
|
||||||
|
unsigned long transition : 1;
|
||||||
|
} lp1;
|
||||||
|
unsigned long lp2;
|
||||||
|
} KEYLP;
|
||||||
|
|
||||||
|
int KbdMessage( KEV kev, WPARAM *pwParam, LPARAM *plParam )
|
||||||
|
{
|
||||||
|
UINT message;
|
||||||
|
int VKey = GETVKEY[kev];
|
||||||
|
KEYLP keylp;
|
||||||
|
|
||||||
|
keylp.lp2 = 0;
|
||||||
|
|
||||||
|
keylp.lp1.count = 1;
|
||||||
|
keylp.lp1.code = GETSCAN[kev];
|
||||||
|
keylp.lp1.extended = 0 ;/* FIXME (ki->dwFlags & KEYEVENTF_EXTENDEDKEY) != 0; */
|
||||||
|
keylp.lp1.win_internal = 0;
|
||||||
|
|
||||||
|
if (GETUPDOWN[kev] & KEYEVENTF_KEYUP )
|
||||||
|
{
|
||||||
|
message = WM_KEYUP;
|
||||||
|
if( (InputKeyStateTable[VK_MENU] & 0x80) && (
|
||||||
|
(VKey == VK_MENU) || (VKey == VK_CONTROL) ||
|
||||||
|
!(InputKeyStateTable[VK_CONTROL] & 0x80))) {
|
||||||
|
if( TrackSysKey == VK_MENU || /* <ALT>-down/<ALT>-up sequence */
|
||||||
|
(VKey != VK_MENU)) /* <ALT>-down...<something else>-up */
|
||||||
|
message = WM_SYSKEYUP;
|
||||||
|
TrackSysKey = 0;
|
||||||
|
}
|
||||||
|
InputKeyStateTable[VKey] &= ~0x80;
|
||||||
|
keylp.lp1.previous = 1;
|
||||||
|
keylp.lp1.transition = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
keylp.lp1.previous = (InputKeyStateTable[VKey] & 0x80) != 0;
|
||||||
|
keylp.lp1.transition = 0;
|
||||||
|
if (!(InputKeyStateTable[VKey] & 0x80)) InputKeyStateTable[VKey] ^= 0x01;
|
||||||
|
InputKeyStateTable[VKey] |= 0x80;
|
||||||
|
AsyncKeyStateTable[VKey] |= 0x80;
|
||||||
|
|
||||||
|
message = WM_KEYDOWN;
|
||||||
|
if( (InputKeyStateTable[VK_MENU] & 0x80) &&
|
||||||
|
!(InputKeyStateTable[VK_CONTROL] & 0x80)) {
|
||||||
|
message = WM_SYSKEYDOWN;
|
||||||
|
TrackSysKey = VKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keylp.lp1.context = (InputKeyStateTable[VK_MENU] & 0x80) != 0; /* 1 if alt */
|
||||||
|
|
||||||
|
if( plParam) *plParam = keylp.lp2;
|
||||||
|
if( pwParam) *pwParam = VKey;
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************** end copy input.c ****************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* . prepare the keyevents for SendInputs
|
||||||
|
* . calculate the "expected" messages
|
||||||
|
* . Send the events to our window
|
||||||
|
* . retrieve the messages from the input queue
|
||||||
|
* . verify
|
||||||
|
*/
|
||||||
|
void do_test( HWND hwnd, int seqnr, KEV td[] )
|
||||||
|
{
|
||||||
|
INPUT inputs[MAXKEYEVENTS];
|
||||||
|
KMSG expmsg[MAXKEYEVENTS];
|
||||||
|
MSG msg;
|
||||||
|
char buf[100];
|
||||||
|
int evtctr=0, kmctr, i;
|
||||||
|
buf[0]='\0';
|
||||||
|
TrackSysKey=0; /* see input.c */
|
||||||
|
for( i = 0; i < MAXKEYEVENTS; i++) {
|
||||||
|
ADDTOINPUTS(td[i])
|
||||||
|
strcat(buf, getdesc[td[i]]);
|
||||||
|
if(td[i])
|
||||||
|
expmsg[i].message = KbdMessage(td[i], &(expmsg[i].wParam), &(expmsg[i].lParam)); /* see queue_kbd_event() */
|
||||||
|
else
|
||||||
|
expmsg[i].message = 0;
|
||||||
|
}
|
||||||
|
for( kmctr = 0; kmctr < MAXKEYEVENTS && expmsg[kmctr].message; kmctr++)
|
||||||
|
;
|
||||||
|
assert( evtctr <= MAXKEYEVENTS );
|
||||||
|
assert( evtctr == SendInput(evtctr, &inputs[0], sizeof(INPUT)));
|
||||||
|
i = 0;
|
||||||
|
trace("======== key stroke sequence #%d: %s =============\n",
|
||||||
|
seqnr + 1, buf);
|
||||||
|
while( PeekMessage(&msg,hwnd,WM_KEYFIRST,WM_KEYLAST,PM_REMOVE) ) {
|
||||||
|
trace("message[%d] %-15s wParam %04x lParam %08lx time %lx\n", i,
|
||||||
|
MSGNAME[msg.message - WM_KEYFIRST], msg.wParam, msg.lParam, msg.time);
|
||||||
|
if( i < kmctr ) {
|
||||||
|
ok( msg.message == expmsg[i].message &&
|
||||||
|
msg.wParam == expmsg[i].wParam &&
|
||||||
|
msg.lParam == expmsg[i].lParam,
|
||||||
|
"wrong message! expected:\n"
|
||||||
|
"message[%d] %-15s wParam %04x lParam %08lx",i,
|
||||||
|
MSGNAME[(expmsg[i]).message - WM_KEYFIRST],
|
||||||
|
expmsg[i].wParam, expmsg[i].lParam );
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
trace("%d messages retrieved\n", i);
|
||||||
|
ok( i == kmctr, "message count is wrong: got %d expected: %d", i, kmctr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test all combinations of the specified key events */
|
||||||
|
void TestASet( HWND hWnd, int nrkev, KEV kevdwn[], KEV kevup[] )
|
||||||
|
{
|
||||||
|
int i,j,k,l,m,n;
|
||||||
|
static int count=0;
|
||||||
|
KEV kbuf[MAXKEYEVENTS];
|
||||||
|
assert( nrkev==2 || nrkev==3);
|
||||||
|
for(i=0;i<MAXKEYEVENTS;i++) kbuf[i]=0;
|
||||||
|
/* two keys involved gives 4 test cases */
|
||||||
|
if(nrkev==2) {
|
||||||
|
for(i=0;i<nrkev;i++) {
|
||||||
|
for(j=0;j<nrkev;j++) {
|
||||||
|
kbuf[0] = kevdwn[i];
|
||||||
|
kbuf[1] = kevdwn[1-i];
|
||||||
|
kbuf[2] = kevup[j];
|
||||||
|
kbuf[3] = kevup[1-j];
|
||||||
|
do_test( hWnd, count++, kbuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* three keys involved gives 36 test cases */
|
||||||
|
if(nrkev==3){
|
||||||
|
for(i=0;i<nrkev;i++){
|
||||||
|
for(j=0;j<nrkev;j++){
|
||||||
|
if(j==i) continue;
|
||||||
|
for(k=0;k<nrkev;k++){
|
||||||
|
if(k==i || k==j) continue;
|
||||||
|
for(l=0;l<nrkev;l++){
|
||||||
|
for(m=0;m<nrkev;m++){
|
||||||
|
if(m==l) continue;
|
||||||
|
for(n=0;n<nrkev;n++){
|
||||||
|
if(n==l ||n==m) continue;
|
||||||
|
kbuf[0] = kevdwn[i];
|
||||||
|
kbuf[1] = kevdwn[j];
|
||||||
|
kbuf[2] = kevdwn[k];
|
||||||
|
kbuf[3] = kevup[l];
|
||||||
|
kbuf[4] = kevup[m];
|
||||||
|
kbuf[5] = kevup[n];
|
||||||
|
do_test( hWnd, count++, kbuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test each set specified in the global testkeyset array */
|
||||||
|
void TestSysKeys( HWND hWnd)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i=0; testkeyset[i].nrkev;i++)
|
||||||
|
TestASet( hWnd, testkeyset[i].nrkev, testkeyset[i].keydwn,
|
||||||
|
testkeyset[i].keyup);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam,
|
||||||
|
LPARAM lParam )
|
||||||
|
{
|
||||||
|
switch (msg) {
|
||||||
|
case WM_SETFOCUS:
|
||||||
|
/* window has focus, now do the test */
|
||||||
|
if( hWnd == hWndTest) TestSysKeys( hWnd);
|
||||||
|
/* finished :-) */
|
||||||
|
DestroyWindow(hWnd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_DESTROY:
|
||||||
|
PostQuitMessage( 0 );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return( DefWindowProcA( hWnd, msg, wParam, lParam ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(input)
|
||||||
|
{
|
||||||
|
MSG msg;
|
||||||
|
WNDCLASSA wclass;
|
||||||
|
HANDLE hInstance = GetModuleHandleA( NULL );
|
||||||
|
|
||||||
|
wclass.lpszClassName = "InputSysKeyTestClass";
|
||||||
|
wclass.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
|
wclass.lpfnWndProc = (WNDPROC)WndProc;
|
||||||
|
wclass.hInstance = hInstance;
|
||||||
|
wclass.hIcon = LoadIconA( 0, (LPSTR)IDI_APPLICATION );
|
||||||
|
wclass.hCursor = LoadCursorA( NULL, IDC_ARROW);
|
||||||
|
wclass.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1);
|
||||||
|
wclass.lpszMenuName = 0;
|
||||||
|
wclass.cbClsExtra = 0;
|
||||||
|
wclass.cbWndExtra = 0;
|
||||||
|
assert (RegisterClassA( &wclass ));
|
||||||
|
/* create the test window that will receive the keystrokes */
|
||||||
|
assert ( hWndTest = CreateWindowA( wclass.lpszClassName, "InputSysKeyTest",
|
||||||
|
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 100, 100,
|
||||||
|
NULL, NULL, hInstance, NULL) );
|
||||||
|
ShowWindow( hWndTest, SW_SHOW);
|
||||||
|
UpdateWindow( hWndTest);
|
||||||
|
/* message loop */
|
||||||
|
while( GetMessageA( &msg, 0, 0, 0 )) {
|
||||||
|
TranslateMessage( &msg );
|
||||||
|
DispatchMessageA( &msg );
|
||||||
|
}
|
||||||
|
}
|
173
reactos/apps/tests/user32/listbox.c
Normal file
173
reactos/apps/tests/user32/listbox.c
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
/* Unit test suite for list boxes.
|
||||||
|
*
|
||||||
|
* Copyright 2003 Ferenc Wagner
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "wine/test.h"
|
||||||
|
|
||||||
|
#ifdef VISIBLE
|
||||||
|
#define WAIT Sleep (1000)
|
||||||
|
#define REDRAW RedrawWindow (handle, NULL, 0, RDW_UPDATENOW)
|
||||||
|
#else
|
||||||
|
#define WAIT
|
||||||
|
#define REDRAW
|
||||||
|
#endif
|
||||||
|
|
||||||
|
HWND
|
||||||
|
create_listbox (DWORD add_style)
|
||||||
|
{
|
||||||
|
HWND handle=CreateWindow ("LISTBOX", "TestList",
|
||||||
|
(LBS_STANDARD & ~LBS_SORT) | add_style,
|
||||||
|
0, 0, 100, 100,
|
||||||
|
NULL, NULL, NULL, 0);
|
||||||
|
|
||||||
|
assert (handle);
|
||||||
|
SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) "First added");
|
||||||
|
SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) "Second added");
|
||||||
|
SendMessage (handle, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) "Third added");
|
||||||
|
|
||||||
|
#ifdef VISIBLE
|
||||||
|
ShowWindow (handle, SW_SHOW);
|
||||||
|
#endif
|
||||||
|
REDRAW;
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct listbox_prop {
|
||||||
|
DWORD add_style;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct listbox_stat {
|
||||||
|
int selected, anchor, caret, selcount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct listbox_test {
|
||||||
|
struct listbox_prop prop;
|
||||||
|
struct listbox_stat init, init_todo;
|
||||||
|
struct listbox_stat click, click_todo;
|
||||||
|
struct listbox_stat step, step_todo;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
listbox_query (HWND handle, struct listbox_stat *results)
|
||||||
|
{
|
||||||
|
results->selected = SendMessage (handle, LB_GETCURSEL, 0, 0);
|
||||||
|
results->anchor = SendMessage (handle, LB_GETANCHORINDEX, 0, 0);
|
||||||
|
results->caret = SendMessage (handle, LB_GETCARETINDEX, 0, 0);
|
||||||
|
results->selcount = SendMessage (handle, LB_GETSELCOUNT, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
buttonpress (HWND handle, WORD x, WORD y)
|
||||||
|
{
|
||||||
|
LPARAM lp=x+(y<<16);
|
||||||
|
|
||||||
|
WAIT;
|
||||||
|
SendMessage (handle, WM_LBUTTONDOWN, (WPARAM) MK_LBUTTON, lp);
|
||||||
|
SendMessage (handle, WM_LBUTTONUP , (WPARAM) 0 , lp);
|
||||||
|
REDRAW;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
keypress (HWND handle, WPARAM keycode, BYTE scancode, BOOL extended)
|
||||||
|
{
|
||||||
|
LPARAM lp=1+(scancode<<16)+(extended?KEYEVENTF_EXTENDEDKEY:0);
|
||||||
|
|
||||||
|
WAIT;
|
||||||
|
SendMessage (handle, WM_KEYDOWN, keycode, lp);
|
||||||
|
SendMessage (handle, WM_KEYUP , keycode, lp | 0xc000000);
|
||||||
|
REDRAW;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define listbox_field_ok(t, s, f, got) \
|
||||||
|
ok (t.s.f==got.f, "style %#x, step " #s ", field " #f \
|
||||||
|
": expected %d, got %d", (unsigned int)t.prop.add_style, \
|
||||||
|
t.s.f, got.f)
|
||||||
|
|
||||||
|
#define listbox_todo_field_ok(t, s, f, got) \
|
||||||
|
if (t.s##_todo.f) todo_wine { listbox_field_ok(t, s, f, got); } \
|
||||||
|
else listbox_field_ok(t, s, f, got)
|
||||||
|
|
||||||
|
#define listbox_ok(t, s, got) \
|
||||||
|
listbox_todo_field_ok(t, s, selected, got); \
|
||||||
|
listbox_todo_field_ok(t, s, anchor, got); \
|
||||||
|
listbox_todo_field_ok(t, s, caret, got); \
|
||||||
|
listbox_todo_field_ok(t, s, selcount, got)
|
||||||
|
|
||||||
|
void
|
||||||
|
check (const struct listbox_test test)
|
||||||
|
{
|
||||||
|
struct listbox_stat answer;
|
||||||
|
HWND hLB=create_listbox (test.prop.add_style);
|
||||||
|
RECT second_item;
|
||||||
|
|
||||||
|
listbox_query (hLB, &answer);
|
||||||
|
listbox_ok (test, init, answer);
|
||||||
|
|
||||||
|
SendMessage (hLB, LB_GETITEMRECT, (WPARAM) 1, (LPARAM) &second_item);
|
||||||
|
buttonpress(hLB, (WORD)second_item.left, (WORD)second_item.top);
|
||||||
|
|
||||||
|
listbox_query (hLB, &answer);
|
||||||
|
listbox_ok (test, click, answer);
|
||||||
|
|
||||||
|
keypress (hLB, VK_DOWN, 0x50, TRUE);
|
||||||
|
|
||||||
|
listbox_query (hLB, &answer);
|
||||||
|
listbox_ok (test, step, answer);
|
||||||
|
|
||||||
|
WAIT;
|
||||||
|
DestroyWindow (hLB);
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(listbox)
|
||||||
|
{
|
||||||
|
const struct listbox_test SS =
|
||||||
|
/* {add_style} */
|
||||||
|
{{0},
|
||||||
|
{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
|
||||||
|
{ 1, 1, 1, LB_ERR}, {0,1,0,0},
|
||||||
|
{ 2, 2, 2, LB_ERR}, {0,1,0,0}};
|
||||||
|
/* {selected, anchor, caret, selcount}{TODO fields} */
|
||||||
|
const struct listbox_test SS_NS =
|
||||||
|
{{LBS_NOSEL},
|
||||||
|
{LB_ERR, LB_ERR, 0, LB_ERR}, {0,0,0,0},
|
||||||
|
{ 1, 1, 1, LB_ERR}, {1,1,0,0},
|
||||||
|
{ 2, 2, 2, LB_ERR}, {1,1,1,0}};
|
||||||
|
const struct listbox_test MS =
|
||||||
|
{{LBS_MULTIPLESEL},
|
||||||
|
{ 0, LB_ERR, 0, 0}, {0,0,0,0},
|
||||||
|
{ 1, 1, 1, 1}, {0,1,0,0},
|
||||||
|
{ 2, 1, 2, 1}, {0,1,0,1}};
|
||||||
|
const struct listbox_test MS_NS =
|
||||||
|
{{LBS_MULTIPLESEL | LBS_NOSEL},
|
||||||
|
{LB_ERR, LB_ERR, 0, LB_ERR}, {1,0,0,1},
|
||||||
|
{ 1, 1, 1, LB_ERR}, {0,1,0,1},
|
||||||
|
{ 2, 2, 2, LB_ERR}, {0,1,0,1}};
|
||||||
|
|
||||||
|
trace (" Testing single selection...\n");
|
||||||
|
check (SS);
|
||||||
|
trace (" ... with NOSEL\n");
|
||||||
|
check (SS_NS);
|
||||||
|
trace (" Testing multiple selection...\n");
|
||||||
|
check (MS);
|
||||||
|
trace (" ... with NOSEL\n");
|
||||||
|
check (MS_NS);
|
||||||
|
}
|
31
reactos/apps/tests/user32/makefile
Normal file
31
reactos/apps/tests/user32/makefile
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# $Id: makefile,v 1.1 2003/11/18 22:24:42 sedwards Exp $
|
||||||
|
|
||||||
|
PATH_TO_TOP = ../../..
|
||||||
|
|
||||||
|
TARGET_NORC = yes
|
||||||
|
|
||||||
|
TARGET_TYPE = program
|
||||||
|
|
||||||
|
TARGET_APPTYPE = console
|
||||||
|
|
||||||
|
# require os code to explicitly request A/W version of structs/functions
|
||||||
|
TARGET_CFLAGS += -D_DISABLE_TIDENTS -D__USE_W32API
|
||||||
|
|
||||||
|
TARGET_NAME = user32_test
|
||||||
|
|
||||||
|
TARGET_SDKLIBS = gdi32.a user32.a
|
||||||
|
|
||||||
|
TARGET_OBJECTS = \
|
||||||
|
testlist.o \
|
||||||
|
class.o \
|
||||||
|
listbox.o \
|
||||||
|
msg.o \
|
||||||
|
sysparams.o \
|
||||||
|
win.o \
|
||||||
|
wsprintf.o
|
||||||
|
|
||||||
|
include $(PATH_TO_TOP)/rules.mak
|
||||||
|
|
||||||
|
include $(TOOLS_PATH)/helper.mk
|
||||||
|
|
||||||
|
# EOF
|
484
reactos/apps/tests/user32/msg.c
Normal file
484
reactos/apps/tests/user32/msg.c
Normal file
|
@ -0,0 +1,484 @@
|
||||||
|
/*
|
||||||
|
* Unit tests for window message handling
|
||||||
|
*
|
||||||
|
* Copyright 1999 Ove Kaaven
|
||||||
|
* Copyright 2003 Dimitrie O. Paun
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "wingdi.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
|
||||||
|
#include "wine/test.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
FIXME: add tests for these
|
||||||
|
Window Edge Styles (Win31/Win95/98 look), in order of precedence:
|
||||||
|
WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
|
||||||
|
WS_THICKFRAME: thick border
|
||||||
|
WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
|
||||||
|
WS_BORDER (default for overlapped windows): single black border
|
||||||
|
none (default for child (and popup?) windows): no border
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
sent=0x1, posted=0x2, parent=0x4, wparam=0x8, lparam=0x10,
|
||||||
|
defwinproc=0x20
|
||||||
|
} msg_flags_t;
|
||||||
|
|
||||||
|
struct message {
|
||||||
|
UINT message; /* the WM_* code */
|
||||||
|
msg_flags_t flags; /* message props */
|
||||||
|
WPARAM wParam; /* expacted value of wParam */
|
||||||
|
LPARAM lParam; /* expacted value of lParam */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* CreateWindow (for overlapped window, not initially visible) (16/32) */
|
||||||
|
static struct message WmCreateOverlappedSeq[] = {
|
||||||
|
{ WM_GETMINMAXINFO, sent },
|
||||||
|
{ WM_NCCREATE, sent },
|
||||||
|
{ WM_NCCALCSIZE, sent|wparam, 0 },
|
||||||
|
{ WM_CREATE, sent },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
/* ShowWindow (for overlapped window) (16/32) */
|
||||||
|
static struct message WmShowOverlappedSeq[] = {
|
||||||
|
{ WM_SHOWWINDOW, sent|wparam, 1 },
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent|wparam, /*FIXME: SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW*/ 0 },
|
||||||
|
/* FIXME: WM_QUERYNEWPALETTE, if in 256-color mode */
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent|wparam, /*FIXME: SWP_NOMOVE|SWP_NOSIZE*/ 0 },
|
||||||
|
{ WM_ACTIVATEAPP, sent|wparam, 1 },
|
||||||
|
{ WM_NCACTIVATE, sent|wparam, 1 },
|
||||||
|
{ WM_GETTEXT, sent|defwinproc },
|
||||||
|
{ WM_ACTIVATE, sent|wparam, 1 },
|
||||||
|
{ WM_SETFOCUS, sent|wparam|defwinproc, 0 },
|
||||||
|
{ WM_NCPAINT, sent|wparam, 1 },
|
||||||
|
{ WM_GETTEXT, sent|defwinproc },
|
||||||
|
{ WM_ERASEBKGND, sent },
|
||||||
|
{ WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_SHOWWINDOW },
|
||||||
|
{ WM_SIZE, sent },
|
||||||
|
{ WM_MOVE, sent },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* DestroyWindow (for overlapped window) (32) */
|
||||||
|
static struct message WmDestroyOverlappedSeq[] = {
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent|wparam, 0 },
|
||||||
|
{ WM_WINDOWPOSCHANGED, sent|wparam, 0 },
|
||||||
|
{ WM_NCACTIVATE, sent|wparam, 0 },
|
||||||
|
{ WM_ACTIVATE, sent|wparam, 0 },
|
||||||
|
{ WM_ACTIVATEAPP, sent|wparam, 0 },
|
||||||
|
{ WM_KILLFOCUS, sent|wparam, 0 },
|
||||||
|
{ WM_DESTROY, sent },
|
||||||
|
{ WM_NCDESTROY, sent },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
/* CreateWindow (for child window, not initially visible) */
|
||||||
|
static struct message WmCreateChildSeq[] = {
|
||||||
|
{ WM_NCCREATE, sent },
|
||||||
|
/* child is inserted into parent's child list after WM_NCCREATE returns */
|
||||||
|
{ WM_NCCALCSIZE, sent|wparam, 0 },
|
||||||
|
{ WM_CREATE, sent },
|
||||||
|
{ WM_SIZE, sent },
|
||||||
|
{ WM_MOVE, sent },
|
||||||
|
{ WM_PARENTNOTIFY, sent|parent|wparam, 1 },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
/* ShowWindow (for child window) */
|
||||||
|
static struct message WmShowChildSeq[] = {
|
||||||
|
{ WM_SHOWWINDOW, sent|wparam, 1 },
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent|wparam, 0 },
|
||||||
|
{ WM_ERASEBKGND, sent|parent },
|
||||||
|
{ WM_WINDOWPOSCHANGED, sent|wparam, 0 },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
/* DestroyWindow (for child window) */
|
||||||
|
static struct message WmDestroyChildSeq[] = {
|
||||||
|
{ WM_PARENTNOTIFY, sent|parent|wparam, 2 },
|
||||||
|
{ WM_SHOWWINDOW, sent|wparam, 0 },
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent|wparam, 0 },
|
||||||
|
{ WM_ERASEBKGND, sent|parent },
|
||||||
|
{ WM_WINDOWPOSCHANGED, sent|wparam, 0 },
|
||||||
|
{ WM_DESTROY, sent },
|
||||||
|
{ WM_NCDESTROY, sent },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
/* Moving the mouse in nonclient area */
|
||||||
|
static struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
|
||||||
|
{ WM_NCHITTEST, sent },
|
||||||
|
{ WM_SETCURSOR, sent },
|
||||||
|
{ WM_NCMOUSEMOVE, posted },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
/* Moving the mouse in client area */
|
||||||
|
static struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */
|
||||||
|
{ WM_NCHITTEST, sent },
|
||||||
|
{ WM_SETCURSOR, sent },
|
||||||
|
{ WM_MOUSEMOVE, posted },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
/* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
|
||||||
|
static struct message WmDragTitleBarSeq[] = { /* FIXME: add */
|
||||||
|
{ WM_NCLBUTTONDOWN, sent|wparam, HTCAPTION },
|
||||||
|
{ WM_SYSCOMMAND, sent|defwinproc|wparam, SC_MOVE+2 },
|
||||||
|
{ WM_GETMINMAXINFO, sent|defwinproc },
|
||||||
|
{ WM_ENTERSIZEMOVE, sent|defwinproc },
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent|defwinproc },
|
||||||
|
{ WM_WINDOWPOSCHANGED, sent|defwinproc },
|
||||||
|
{ WM_MOVE, sent|defwinproc },
|
||||||
|
{ WM_EXITSIZEMOVE, sent|defwinproc },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
/* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
|
||||||
|
static struct message WmDragThinkBordersBarSeq[] = { /* FIXME: add */
|
||||||
|
{ WM_NCLBUTTONDOWN, sent|wparam, 0xd },
|
||||||
|
{ WM_SYSCOMMAND, sent|defwinproc|wparam, 0xf004 },
|
||||||
|
{ WM_GETMINMAXINFO, sent|defwinproc },
|
||||||
|
{ WM_ENTERSIZEMOVE, sent|defwinproc },
|
||||||
|
{ WM_SIZING, sent|defwinproc|wparam, 4}, /* one for each mouse movement */
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent|defwinproc },
|
||||||
|
{ WM_GETMINMAXINFO, sent|defwinproc },
|
||||||
|
{ WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
|
||||||
|
{ WM_NCPAINT, sent|defwinproc|wparam, 1 },
|
||||||
|
{ WM_GETTEXT, sent|defwinproc },
|
||||||
|
{ WM_ERASEBKGND, sent|defwinproc },
|
||||||
|
{ WM_WINDOWPOSCHANGED, sent|defwinproc },
|
||||||
|
{ WM_MOVE, sent|defwinproc },
|
||||||
|
{ WM_SIZE, sent|defwinproc },
|
||||||
|
{ WM_EXITSIZEMOVE, sent|defwinproc },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
/* Resizing child window with MoveWindow (32) */
|
||||||
|
static struct message WmResizingChildWithMoveWindowSeq[] = {
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent },
|
||||||
|
{ WM_NCCALCSIZE, sent|wparam, 1 },
|
||||||
|
{ WM_ERASEBKGND, sent },
|
||||||
|
{ WM_WINDOWPOSCHANGED, sent },
|
||||||
|
{ WM_MOVE, sent|defwinproc },
|
||||||
|
{ WM_SIZE, sent|defwinproc },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
/* Clicking on inactive button */
|
||||||
|
static struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */
|
||||||
|
{ WM_NCHITTEST, sent },
|
||||||
|
{ WM_PARENTNOTIFY, sent|parent|wparam, WM_LBUTTONDOWN },
|
||||||
|
{ WM_MOUSEACTIVATE, sent },
|
||||||
|
{ WM_MOUSEACTIVATE, sent|parent|defwinproc },
|
||||||
|
{ WM_SETCURSOR, sent },
|
||||||
|
{ WM_SETCURSOR, sent|parent|defwinproc },
|
||||||
|
{ WM_LBUTTONDOWN, posted },
|
||||||
|
{ WM_KILLFOCUS, posted|parent },
|
||||||
|
{ WM_SETFOCUS, posted },
|
||||||
|
{ WM_CTLCOLORBTN, posted|parent },
|
||||||
|
{ BM_SETSTATE, posted },
|
||||||
|
{ WM_CTLCOLORBTN, posted|parent },
|
||||||
|
{ WM_LBUTTONUP, posted },
|
||||||
|
{ BM_SETSTATE, posted },
|
||||||
|
{ WM_CTLCOLORBTN, posted|parent },
|
||||||
|
{ WM_COMMAND, posted|parent },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
/* Reparenting a button (16/32) */
|
||||||
|
/* The last child (button) reparented gets topmost for its new parent. */
|
||||||
|
static struct message WmReparentButtonSeq[] = { /* FIXME: add */
|
||||||
|
{ WM_SHOWWINDOW, sent|wparam, 0 },
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
|
||||||
|
{ WM_ERASEBKGND, sent|parent },
|
||||||
|
{ WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOZORDER },
|
||||||
|
{ WM_CHILDACTIVATE, sent },
|
||||||
|
{ WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER },
|
||||||
|
{ WM_MOVE, sent|defwinproc },
|
||||||
|
{ WM_SHOWWINDOW, sent|wparam, 1 },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
/* Creation of a modal dialog (32) */
|
||||||
|
static struct message WmCreateModalDialogSeq[] = { /* FIXME: add */
|
||||||
|
{ WM_CANCELMODE, sent|parent },
|
||||||
|
{ WM_KILLFOCUS, sent|parent },
|
||||||
|
{ WM_ENABLE, sent|parent|wparam, 0 },
|
||||||
|
/* (window proc creation messages not tracked yet, because...) */
|
||||||
|
{ WM_SETFONT, sent },
|
||||||
|
{ WM_INITDIALOG, sent },
|
||||||
|
/* (...the window proc message hook was installed here, IsVisible still FALSE) */
|
||||||
|
{ WM_NCACTIVATE, sent|parent|wparam, 0 },
|
||||||
|
{ WM_GETTEXT, sent|defwinproc },
|
||||||
|
{ WM_ACTIVATE, sent|parent|wparam, 0 },
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent },
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent|parent },
|
||||||
|
{ WM_NCACTIVATE, sent|wparam, 1 },
|
||||||
|
{ WM_ACTIVATE, sent|wparam, 1 },
|
||||||
|
/* (setting focus) */
|
||||||
|
{ WM_SHOWWINDOW, sent|wparam, 1 },
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent },
|
||||||
|
{ WM_NCPAINT, sent },
|
||||||
|
{ WM_GETTEXT, sent|defwinproc },
|
||||||
|
{ WM_ERASEBKGND, sent },
|
||||||
|
{ WM_CTLCOLORDLG, sent|defwinproc },
|
||||||
|
{ WM_WINDOWPOSCHANGED, sent },
|
||||||
|
{ WM_PAINT, sent },
|
||||||
|
/* FIXME: (bunch of WM_CTLCOLOR* for each control) */
|
||||||
|
{ WM_PAINT, sent|parent },
|
||||||
|
{ WM_ENTERIDLE, sent|parent|wparam, 0},
|
||||||
|
{ WM_SETCURSOR, sent|parent },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
/* Destruction of a modal dialog (32) */
|
||||||
|
static struct message WmDestroyModalDialogSeq[] = { /* FIXME: add */
|
||||||
|
/* (inside dialog proc: EndDialog is called) */
|
||||||
|
{ WM_ENABLE, sent|parent|wparam, 1 },
|
||||||
|
{ WM_SETFOCUS, sent },
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent },
|
||||||
|
{ WM_NCPAINT, sent|parent },
|
||||||
|
{ WM_GETTEXT, sent|defwinproc },
|
||||||
|
{ WM_ERASEBKGND, sent|parent },
|
||||||
|
{ WM_WINDOWPOSCHANGED, sent },
|
||||||
|
{ WM_NCACTIVATE, sent|wparam, 0 },
|
||||||
|
{ WM_ACTIVATE, sent|wparam, 0 },
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent },
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent|parent },
|
||||||
|
{ WM_NCACTIVATE, sent|parent|wparam, 1 },
|
||||||
|
{ WM_GETTEXT, sent|defwinproc },
|
||||||
|
{ WM_ACTIVATE, sent|parent|wparam, 1 },
|
||||||
|
{ WM_KILLFOCUS, sent },
|
||||||
|
{ WM_SETFOCUS, sent|parent },
|
||||||
|
{ WM_DESTROY, sent },
|
||||||
|
{ WM_NCDESTROY, sent },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
/* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
|
||||||
|
static struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */
|
||||||
|
/* (inside dialog proc, handling WM_INITDIALOG) */
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent },
|
||||||
|
{ WM_NCCALCSIZE, sent },
|
||||||
|
{ WM_NCACTIVATE, sent|parent|wparam, 0 },
|
||||||
|
{ WM_GETTEXT, sent|defwinproc },
|
||||||
|
{ WM_ACTIVATE, sent|parent|wparam, 0 },
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent },
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent|parent },
|
||||||
|
{ WM_NCACTIVATE, sent|wparam, 1 },
|
||||||
|
{ WM_ACTIVATE, sent|wparam, 1 },
|
||||||
|
{ WM_WINDOWPOSCHANGED, sent },
|
||||||
|
{ WM_SIZE, sent|defwinproc },
|
||||||
|
/* (setting focus) */
|
||||||
|
{ WM_SHOWWINDOW, sent|wparam, 1 },
|
||||||
|
{ WM_WINDOWPOSCHANGING, sent },
|
||||||
|
{ WM_NCPAINT, sent },
|
||||||
|
{ WM_GETTEXT, sent|defwinproc },
|
||||||
|
{ WM_ERASEBKGND, sent },
|
||||||
|
{ WM_CTLCOLORDLG, sent|defwinproc },
|
||||||
|
{ WM_WINDOWPOSCHANGED, sent },
|
||||||
|
{ WM_PAINT, sent },
|
||||||
|
/* (bunch of WM_CTLCOLOR* for each control) */
|
||||||
|
{ WM_PAINT, sent|parent },
|
||||||
|
{ WM_ENTERIDLE, sent|parent|wparam, 0 },
|
||||||
|
{ WM_SETCURSOR, sent|parent },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int sequence_cnt, sequence_size;
|
||||||
|
static struct message* sequence;
|
||||||
|
|
||||||
|
static void add_message(struct message msg)
|
||||||
|
{
|
||||||
|
if (!sequence)
|
||||||
|
sequence = malloc ( (sequence_size = 10) * sizeof (struct message) );
|
||||||
|
if (sequence_cnt == sequence_size)
|
||||||
|
sequence = realloc ( sequence, (sequence_size *= 2) * sizeof (struct message) );
|
||||||
|
assert(sequence);
|
||||||
|
sequence[sequence_cnt++] = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flush_sequence()
|
||||||
|
{
|
||||||
|
free(sequence);
|
||||||
|
sequence = 0;
|
||||||
|
sequence_cnt = sequence_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ok_sequence(struct message *expected, const char *context)
|
||||||
|
{
|
||||||
|
static struct message end_of_sequence = { 0, 0, 0, 0 };
|
||||||
|
struct message *actual = sequence;
|
||||||
|
|
||||||
|
add_message(end_of_sequence);
|
||||||
|
|
||||||
|
/* naive sequence comparison. Would be nice to use a regexp engine here */
|
||||||
|
while (expected->message || actual->message)
|
||||||
|
{
|
||||||
|
if (expected->message == actual->message)
|
||||||
|
{
|
||||||
|
if (expected->flags & wparam)
|
||||||
|
ok (expected->wParam == actual->wParam,
|
||||||
|
"%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
|
||||||
|
context, expected->message, expected->wParam, actual->wParam);
|
||||||
|
if (expected->flags & lparam)
|
||||||
|
ok (expected->lParam == actual->lParam,
|
||||||
|
"%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
|
||||||
|
context, expected->message, expected->lParam, actual->lParam);
|
||||||
|
/* FIXME: should we check defwinproc? */
|
||||||
|
ok ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
|
||||||
|
"%s: the msg 0x%04x should have been %s\n",
|
||||||
|
context, expected->message, (expected->flags & posted) ? "posted" : "sent");
|
||||||
|
ok ((expected->flags & parent) == (actual->flags & parent),
|
||||||
|
"%s: the msg 0x%04x was expected in %s\n",
|
||||||
|
context, expected->message, (expected->flags & parent) ? "parent" : "child");
|
||||||
|
expected++;
|
||||||
|
actual++;
|
||||||
|
}
|
||||||
|
else if (expected->message && ((expected + 1)->message == actual->message) )
|
||||||
|
{
|
||||||
|
todo_wine {
|
||||||
|
ok (FALSE, "%s: the msg 0x%04x was not received\n", context, expected->message);
|
||||||
|
expected++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (actual->message && (expected->message == (actual + 1)->message) )
|
||||||
|
{
|
||||||
|
todo_wine {
|
||||||
|
ok (FALSE, "%s: the msg 0x%04x was not expected\n", context, actual->message);
|
||||||
|
actual++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
todo_wine {
|
||||||
|
ok (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
|
||||||
|
context, expected->message, actual->message);
|
||||||
|
expected++;
|
||||||
|
actual++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flush_sequence();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test if we receive the right sequence of messages */
|
||||||
|
static void test_messages(void)
|
||||||
|
{
|
||||||
|
HWND hwnd, hparent, hchild;
|
||||||
|
HWND hchild2, hbutton;
|
||||||
|
|
||||||
|
hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
|
||||||
|
100, 100, 200, 200, 0, 0, 0, NULL);
|
||||||
|
ok (hwnd != 0, "Failed to create overlapped window\n");
|
||||||
|
ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped");
|
||||||
|
|
||||||
|
ShowWindow(hwnd, TRUE);
|
||||||
|
ok_sequence(WmShowOverlappedSeq, "ShowWindow:overlapped");
|
||||||
|
|
||||||
|
DestroyWindow(hwnd);
|
||||||
|
ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped");
|
||||||
|
|
||||||
|
hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW,
|
||||||
|
100, 100, 200, 200, 0, 0, 0, NULL);
|
||||||
|
ok (hparent != 0, "Failed to create parent window\n");
|
||||||
|
flush_sequence();
|
||||||
|
|
||||||
|
hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILDWINDOW,
|
||||||
|
0, 0, 10, 10, hparent, 0, 0, NULL);
|
||||||
|
ok (hchild != 0, "Failed to create child window\n");
|
||||||
|
ok_sequence(WmCreateChildSeq, "CreateWindow:child");
|
||||||
|
|
||||||
|
hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILDWINDOW,
|
||||||
|
100, 100, 50, 50, hparent, 0, 0, NULL);
|
||||||
|
ok (hchild2 != 0, "Failed to create child2 window\n");
|
||||||
|
flush_sequence();
|
||||||
|
|
||||||
|
hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILDWINDOW,
|
||||||
|
0, 100, 50, 50, hchild, 0, 0, NULL);
|
||||||
|
ok (hbutton != 0, "Failed to create button window\n");
|
||||||
|
flush_sequence();
|
||||||
|
|
||||||
|
ShowWindow(hchild, TRUE);
|
||||||
|
ok_sequence(WmShowChildSeq, "ShowWindow:child");
|
||||||
|
|
||||||
|
MoveWindow(hchild, 10, 10, 20, 20, TRUE);
|
||||||
|
ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child");
|
||||||
|
|
||||||
|
DestroyWindow(hchild);
|
||||||
|
ok_sequence(WmDestroyChildSeq, "DestroyWindow:child");
|
||||||
|
}
|
||||||
|
|
||||||
|
static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
struct message msg = { message, sent|wparam|lparam, wParam, lParam };
|
||||||
|
|
||||||
|
add_message(msg);
|
||||||
|
return DefWindowProcA(hwnd, message, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL RegisterWindowClasses(void)
|
||||||
|
{
|
||||||
|
WNDCLASSA cls;
|
||||||
|
|
||||||
|
cls.style = 0;
|
||||||
|
cls.lpfnWndProc = MsgCheckProcA;
|
||||||
|
cls.cbClsExtra = 0;
|
||||||
|
cls.cbWndExtra = 0;
|
||||||
|
cls.hInstance = GetModuleHandleA(0);
|
||||||
|
cls.hIcon = 0;
|
||||||
|
cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
|
||||||
|
cls.hbrBackground = GetStockObject(WHITE_BRUSH);
|
||||||
|
cls.lpszMenuName = NULL;
|
||||||
|
cls.lpszClassName = "TestWindowClass";
|
||||||
|
|
||||||
|
if(!RegisterClassA(&cls)) return FALSE;
|
||||||
|
|
||||||
|
cls.style = 0;
|
||||||
|
cls.lpfnWndProc = DefWindowProcA;
|
||||||
|
cls.cbClsExtra = 0;
|
||||||
|
cls.cbWndExtra = 0;
|
||||||
|
cls.hInstance = GetModuleHandleA(0);
|
||||||
|
cls.hIcon = 0;
|
||||||
|
cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
|
||||||
|
cls.hbrBackground = GetStockObject(WHITE_BRUSH);
|
||||||
|
cls.lpszMenuName = NULL;
|
||||||
|
cls.lpszClassName = "TestParentClass";
|
||||||
|
|
||||||
|
if(!RegisterClassA(&cls)) return FALSE;
|
||||||
|
|
||||||
|
cls.style = 0;
|
||||||
|
cls.lpfnWndProc = DefWindowProcA;
|
||||||
|
cls.cbClsExtra = 0;
|
||||||
|
cls.cbWndExtra = 0;
|
||||||
|
cls.hInstance = GetModuleHandleA(0);
|
||||||
|
cls.hIcon = 0;
|
||||||
|
cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
|
||||||
|
cls.hbrBackground = GetStockObject(WHITE_BRUSH);
|
||||||
|
cls.lpszMenuName = NULL;
|
||||||
|
cls.lpszClassName = "SimpleWindowClass";
|
||||||
|
|
||||||
|
if(!RegisterClassA(&cls)) return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(msg)
|
||||||
|
{
|
||||||
|
if (!RegisterWindowClasses()) assert(0);
|
||||||
|
|
||||||
|
test_messages();
|
||||||
|
}
|
1136
reactos/apps/tests/user32/sysparams.c
Normal file
1136
reactos/apps/tests/user32/sysparams.c
Normal file
File diff suppressed because it is too large
Load diff
34
reactos/apps/tests/user32/testlist.c
Normal file
34
reactos/apps/tests/user32/testlist.c
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/* Automatically generated file; DO NOT EDIT!! */
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
|
||||||
|
extern void func_class(void);
|
||||||
|
extern void func_listbox(void);
|
||||||
|
extern void func_msg(void);
|
||||||
|
extern void func_sysparams(void);
|
||||||
|
extern void func_win(void);
|
||||||
|
extern void func_wsprintf(void);
|
||||||
|
|
||||||
|
struct test
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
void (*func)(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct test winetest_testlist[] =
|
||||||
|
{
|
||||||
|
{ "class", func_class },
|
||||||
|
{ "listbox", func_listbox },
|
||||||
|
{ "msg", func_msg },
|
||||||
|
{ "sysparams", func_sysparams },
|
||||||
|
{ "win", func_win },
|
||||||
|
{ "wsprintf", func_wsprintf },
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
#define WINETEST_WANT_MAIN
|
||||||
|
#include "wine/test.h"
|
715
reactos/apps/tests/user32/win.c
Normal file
715
reactos/apps/tests/user32/win.c
Normal file
|
@ -0,0 +1,715 @@
|
||||||
|
/*
|
||||||
|
* Unit tests for window handling
|
||||||
|
*
|
||||||
|
* Copyright 2002 Bill Medland
|
||||||
|
* Copyright 2002 Alexandre Julliard
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "wingdi.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
|
||||||
|
#include "wine/test.h"
|
||||||
|
|
||||||
|
HWND WINAPI GetShellWindow(void);
|
||||||
|
|
||||||
|
#ifndef SPI_GETDESKWALLPAPER
|
||||||
|
#define SPI_GETDESKWALLPAPER 0x0073
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LONG_PTR INT_PTR
|
||||||
|
#define ULONG_PTR UINT_PTR
|
||||||
|
|
||||||
|
static HWND (WINAPI *pGetAncestor)(HWND,UINT);
|
||||||
|
|
||||||
|
static HWND hwndMain, hwndMain2;
|
||||||
|
static HHOOK hhook;
|
||||||
|
|
||||||
|
/* check the values returned by the various parent/owner functions on a given window */
|
||||||
|
static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_parent,
|
||||||
|
HWND gw_owner, HWND ga_root, HWND ga_root_owner )
|
||||||
|
{
|
||||||
|
HWND res;
|
||||||
|
|
||||||
|
if (pGetAncestor)
|
||||||
|
{
|
||||||
|
res = pGetAncestor( hwnd, GA_PARENT );
|
||||||
|
ok( res == ga_parent, "Wrong result for GA_PARENT %p expected %p", res, ga_parent );
|
||||||
|
}
|
||||||
|
res = (HWND)GetWindowLongA( hwnd, GWL_HWNDPARENT );
|
||||||
|
ok( res == gwl_parent, "Wrong result for GWL_HWNDPARENT %p expected %p", res, gwl_parent );
|
||||||
|
res = GetParent( hwnd );
|
||||||
|
ok( res == get_parent, "Wrong result for GetParent %p expected %p", res, get_parent );
|
||||||
|
res = GetWindow( hwnd, GW_OWNER );
|
||||||
|
ok( res == gw_owner, "Wrong result for GW_OWNER %p expected %p", res, gw_owner );
|
||||||
|
if (pGetAncestor)
|
||||||
|
{
|
||||||
|
res = pGetAncestor( hwnd, GA_ROOT );
|
||||||
|
ok( res == ga_root, "Wrong result for GA_ROOT %p expected %p", res, ga_root );
|
||||||
|
res = pGetAncestor( hwnd, GA_ROOTOWNER );
|
||||||
|
ok( res == ga_root_owner, "Wrong result for GA_ROOTOWNER %p expected %p", res, ga_root_owner );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static HWND create_tool_window( LONG style, HWND parent )
|
||||||
|
{
|
||||||
|
HWND ret = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", style,
|
||||||
|
0, 0, 100, 100, parent, 0, 0, NULL );
|
||||||
|
ok( ret != 0, "Creation failed" );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test parent and owner values for various combinations */
|
||||||
|
static void test_parent_owner(void)
|
||||||
|
{
|
||||||
|
LONG style;
|
||||||
|
HWND test, owner, ret;
|
||||||
|
HWND desktop = GetDesktopWindow();
|
||||||
|
HWND child = create_tool_window( WS_CHILD, hwndMain );
|
||||||
|
|
||||||
|
trace( "main window %p main2 %p desktop %p child %p\n", hwndMain, hwndMain2, desktop, child );
|
||||||
|
|
||||||
|
/* child without parent, should fail */
|
||||||
|
test = CreateWindowExA(0, "ToolWindowClass", "Tool window 1",
|
||||||
|
WS_CHILD, 0, 0, 100, 100, 0, 0, 0, NULL );
|
||||||
|
ok( !test, "WS_CHILD without parent created" );
|
||||||
|
|
||||||
|
/* desktop window */
|
||||||
|
check_parents( desktop, 0, 0, 0, 0, 0, 0 );
|
||||||
|
style = GetWindowLongA( desktop, GWL_STYLE );
|
||||||
|
ok( !SetWindowLongA( desktop, GWL_STYLE, WS_POPUP ), "Set GWL_STYLE on desktop succeeded" );
|
||||||
|
ok( !SetWindowLongA( desktop, GWL_STYLE, 0 ), "Set GWL_STYLE on desktop succeeded" );
|
||||||
|
ok( GetWindowLongA( desktop, GWL_STYLE ) == style, "Desktop style changed" );
|
||||||
|
|
||||||
|
/* normal child window */
|
||||||
|
test = create_tool_window( WS_CHILD, hwndMain );
|
||||||
|
trace( "created child %p\n", test );
|
||||||
|
check_parents( test, hwndMain, hwndMain, hwndMain, 0, hwndMain, hwndMain );
|
||||||
|
SetWindowLongA( test, GWL_STYLE, 0 );
|
||||||
|
check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
|
||||||
|
SetWindowLongA( test, GWL_STYLE, WS_POPUP );
|
||||||
|
check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
|
||||||
|
SetWindowLongA( test, GWL_STYLE, WS_POPUP|WS_CHILD );
|
||||||
|
check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
|
||||||
|
SetWindowLongA( test, GWL_STYLE, WS_CHILD );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* normal child window with WS_MAXIMIZE */
|
||||||
|
test = create_tool_window( WS_CHILD | WS_MAXIMIZE, hwndMain );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* normal child window with WS_THICKFRAME */
|
||||||
|
test = create_tool_window( WS_CHILD | WS_THICKFRAME, hwndMain );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* popup window with WS_THICKFRAME */
|
||||||
|
test = create_tool_window( WS_POPUP | WS_THICKFRAME, hwndMain );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* child of desktop */
|
||||||
|
test = create_tool_window( WS_CHILD, desktop );
|
||||||
|
trace( "created child of desktop %p\n", test );
|
||||||
|
check_parents( test, desktop, 0, desktop, 0, test, desktop );
|
||||||
|
SetWindowLongA( test, GWL_STYLE, WS_POPUP );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
SetWindowLongA( test, GWL_STYLE, 0 );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* child of desktop with WS_MAXIMIZE */
|
||||||
|
test = create_tool_window( WS_CHILD | WS_MAXIMIZE, desktop );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* child of desktop with WS_MINIMIZE */
|
||||||
|
test = create_tool_window( WS_CHILD | WS_MINIMIZE, desktop );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* child of child */
|
||||||
|
test = create_tool_window( WS_CHILD, child );
|
||||||
|
trace( "created child of child %p\n", test );
|
||||||
|
check_parents( test, child, child, child, 0, hwndMain, hwndMain );
|
||||||
|
SetWindowLongA( test, GWL_STYLE, 0 );
|
||||||
|
check_parents( test, child, child, 0, 0, hwndMain, test );
|
||||||
|
SetWindowLongA( test, GWL_STYLE, WS_POPUP );
|
||||||
|
check_parents( test, child, child, 0, 0, hwndMain, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* child of child with WS_MAXIMIZE */
|
||||||
|
test = create_tool_window( WS_CHILD | WS_MAXIMIZE, child );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* child of child with WS_MINIMIZE */
|
||||||
|
test = create_tool_window( WS_CHILD | WS_MINIMIZE, child );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* not owned top-level window */
|
||||||
|
test = create_tool_window( 0, 0 );
|
||||||
|
trace( "created top-level %p\n", test );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
SetWindowLongA( test, GWL_STYLE, WS_POPUP );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
SetWindowLongA( test, GWL_STYLE, WS_CHILD );
|
||||||
|
check_parents( test, desktop, 0, desktop, 0, test, desktop );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* not owned top-level window with WS_MAXIMIZE */
|
||||||
|
test = create_tool_window( WS_MAXIMIZE, 0 );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* owned top-level window */
|
||||||
|
test = create_tool_window( 0, hwndMain );
|
||||||
|
trace( "created owned top-level %p\n", test );
|
||||||
|
check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
|
||||||
|
SetWindowLongA( test, GWL_STYLE, WS_POPUP );
|
||||||
|
check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
|
||||||
|
SetWindowLongA( test, GWL_STYLE, WS_CHILD );
|
||||||
|
check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* owned top-level window with WS_MAXIMIZE */
|
||||||
|
test = create_tool_window( WS_MAXIMIZE, hwndMain );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* not owned popup */
|
||||||
|
test = create_tool_window( WS_POPUP, 0 );
|
||||||
|
trace( "created popup %p\n", test );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
SetWindowLongA( test, GWL_STYLE, WS_CHILD );
|
||||||
|
check_parents( test, desktop, 0, desktop, 0, test, desktop );
|
||||||
|
SetWindowLongA( test, GWL_STYLE, 0 );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* not owned popup with WS_MAXIMIZE */
|
||||||
|
test = create_tool_window( WS_POPUP | WS_MAXIMIZE, 0 );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* owned popup */
|
||||||
|
test = create_tool_window( WS_POPUP, hwndMain );
|
||||||
|
trace( "created owned popup %p\n", test );
|
||||||
|
check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
|
||||||
|
SetWindowLongA( test, GWL_STYLE, WS_CHILD );
|
||||||
|
check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
|
||||||
|
SetWindowLongA( test, GWL_STYLE, 0 );
|
||||||
|
check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* owned popup with WS_MAXIMIZE */
|
||||||
|
test = create_tool_window( WS_POPUP | WS_MAXIMIZE, hwndMain );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* top-level window owned by child (same as owned by top-level) */
|
||||||
|
test = create_tool_window( 0, child );
|
||||||
|
trace( "created top-level owned by child %p\n", test );
|
||||||
|
check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* top-level window owned by child (same as owned by top-level) with WS_MAXIMIZE */
|
||||||
|
test = create_tool_window( WS_MAXIMIZE, child );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* popup owned by desktop (same as not owned) */
|
||||||
|
test = create_tool_window( WS_POPUP, desktop );
|
||||||
|
trace( "created popup owned by desktop %p\n", test );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* popup owned by desktop (same as not owned) with WS_MAXIMIZE */
|
||||||
|
test = create_tool_window( WS_POPUP | WS_MAXIMIZE, desktop );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* popup owned by child (same as owned by top-level) */
|
||||||
|
test = create_tool_window( WS_POPUP, child );
|
||||||
|
trace( "created popup owned by child %p\n", test );
|
||||||
|
check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* popup owned by child (same as owned by top-level) with WS_MAXIMIZE */
|
||||||
|
test = create_tool_window( WS_POPUP | WS_MAXIMIZE, child );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* not owned popup with WS_CHILD (same as WS_POPUP only) */
|
||||||
|
test = create_tool_window( WS_POPUP | WS_CHILD, 0 );
|
||||||
|
trace( "created WS_CHILD popup %p\n", test );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* not owned popup with WS_CHILD | WS_MAXIMIZE (same as WS_POPUP only) */
|
||||||
|
test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, 0 );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* owned popup with WS_CHILD (same as WS_POPUP only) */
|
||||||
|
test = create_tool_window( WS_POPUP | WS_CHILD, hwndMain );
|
||||||
|
trace( "created owned WS_CHILD popup %p\n", test );
|
||||||
|
check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* owned popup with WS_CHILD (same as WS_POPUP only) with WS_MAXIMIZE */
|
||||||
|
test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, hwndMain );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/******************** parent changes *************************/
|
||||||
|
trace( "testing parent changes\n" );
|
||||||
|
|
||||||
|
/* desktop window */
|
||||||
|
check_parents( desktop, 0, 0, 0, 0, 0, 0 );
|
||||||
|
#if 0 /* this test succeeds on NT but crashes on win9x systems */
|
||||||
|
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
|
||||||
|
ok( !ret, "Set GWL_HWNDPARENT succeeded on desktop" );
|
||||||
|
check_parents( desktop, 0, 0, 0, 0, 0, 0 );
|
||||||
|
ok( !SetParent( desktop, hwndMain ), "SetParent succeeded on desktop" );
|
||||||
|
check_parents( desktop, 0, 0, 0, 0, 0, 0 );
|
||||||
|
#endif
|
||||||
|
/* normal child window */
|
||||||
|
test = create_tool_window( WS_CHILD, hwndMain );
|
||||||
|
trace( "created child %p\n", test );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
|
||||||
|
ok( ret == hwndMain, "GWL_HWNDPARENT return value %p expected %p", ret, hwndMain );
|
||||||
|
check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
|
||||||
|
ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p", ret, hwndMain2 );
|
||||||
|
check_parents( test, child, child, child, 0, hwndMain, hwndMain );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)desktop );
|
||||||
|
ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
|
||||||
|
check_parents( test, desktop, 0, desktop, 0, test, desktop );
|
||||||
|
|
||||||
|
/* window is now child of desktop so GWL_HWNDPARENT changes owner from now on */
|
||||||
|
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
|
||||||
|
ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0", ret );
|
||||||
|
check_parents( test, desktop, child, desktop, child, test, desktop );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, 0 );
|
||||||
|
ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
|
||||||
|
check_parents( test, desktop, 0, desktop, 0, test, desktop );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* not owned top-level window */
|
||||||
|
test = create_tool_window( 0, 0 );
|
||||||
|
trace( "created top-level %p\n", test );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
|
||||||
|
ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0", ret );
|
||||||
|
check_parents( test, desktop, hwndMain2, 0, hwndMain2, test, test );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
|
||||||
|
ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p", ret, hwndMain2 );
|
||||||
|
check_parents( test, desktop, child, 0, child, test, test );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, 0 );
|
||||||
|
ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* not owned popup */
|
||||||
|
test = create_tool_window( WS_POPUP, 0 );
|
||||||
|
trace( "created popup %p\n", test );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
|
||||||
|
ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0", ret );
|
||||||
|
check_parents( test, desktop, hwndMain2, hwndMain2, hwndMain2, test, hwndMain2 );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
|
||||||
|
ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p", ret, hwndMain2 );
|
||||||
|
check_parents( test, desktop, child, child, child, test, hwndMain );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, 0 );
|
||||||
|
ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
|
||||||
|
check_parents( test, desktop, 0, 0, 0, test, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* normal child window */
|
||||||
|
test = create_tool_window( WS_CHILD, hwndMain );
|
||||||
|
trace( "created child %p\n", test );
|
||||||
|
|
||||||
|
ret = SetParent( test, desktop );
|
||||||
|
ok( ret == hwndMain, "SetParent return value %p expected %p", ret, hwndMain );
|
||||||
|
check_parents( test, desktop, 0, desktop, 0, test, desktop );
|
||||||
|
|
||||||
|
ret = SetParent( test, child );
|
||||||
|
ok( ret == desktop, "SetParent return value %p expected %p", ret, desktop );
|
||||||
|
check_parents( test, child, child, child, 0, hwndMain, hwndMain );
|
||||||
|
|
||||||
|
ret = SetParent( test, hwndMain2 );
|
||||||
|
ok( ret == child, "SetParent return value %p expected %p", ret, child );
|
||||||
|
check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* not owned top-level window */
|
||||||
|
test = create_tool_window( 0, 0 );
|
||||||
|
trace( "created top-level %p\n", test );
|
||||||
|
|
||||||
|
ret = SetParent( test, child );
|
||||||
|
ok( ret == desktop, "SetParent return value %p expected %p", ret, desktop );
|
||||||
|
check_parents( test, child, child, 0, 0, hwndMain, test );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/* owned popup */
|
||||||
|
test = create_tool_window( WS_POPUP, hwndMain2 );
|
||||||
|
trace( "created owned popup %p\n", test );
|
||||||
|
|
||||||
|
ret = SetParent( test, child );
|
||||||
|
ok( ret == desktop, "SetParent return value %p expected %p", ret, desktop );
|
||||||
|
check_parents( test, child, child, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
|
||||||
|
|
||||||
|
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (ULONG_PTR)hwndMain );
|
||||||
|
ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
|
||||||
|
check_parents( test, hwndMain, hwndMain, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
|
||||||
|
DestroyWindow( test );
|
||||||
|
|
||||||
|
/**************** test owner destruction *******************/
|
||||||
|
|
||||||
|
/* owned child popup */
|
||||||
|
owner = create_tool_window( 0, 0 );
|
||||||
|
test = create_tool_window( WS_POPUP, owner );
|
||||||
|
trace( "created owner %p and popup %p\n", owner, test );
|
||||||
|
ret = SetParent( test, child );
|
||||||
|
ok( ret == desktop, "SetParent return value %p expected %p", ret, desktop );
|
||||||
|
check_parents( test, child, child, owner, owner, hwndMain, owner );
|
||||||
|
/* window is now child of 'child' but owned by 'owner' */
|
||||||
|
DestroyWindow( owner );
|
||||||
|
ok( IsWindow(test), "Window %p destroyed by owner destruction", test );
|
||||||
|
check_parents( test, child, child, owner, owner, hwndMain, owner );
|
||||||
|
ok( !IsWindow(owner), "Owner %p not destroyed", owner );
|
||||||
|
DestroyWindow(test);
|
||||||
|
|
||||||
|
/* owned top-level popup */
|
||||||
|
owner = create_tool_window( 0, 0 );
|
||||||
|
test = create_tool_window( WS_POPUP, owner );
|
||||||
|
trace( "created owner %p and popup %p\n", owner, test );
|
||||||
|
check_parents( test, desktop, owner, owner, owner, test, owner );
|
||||||
|
DestroyWindow( owner );
|
||||||
|
ok( !IsWindow(test), "Window %p not destroyed by owner destruction", test );
|
||||||
|
|
||||||
|
/* top-level popup owned by child */
|
||||||
|
owner = create_tool_window( WS_CHILD, hwndMain2 );
|
||||||
|
test = create_tool_window( WS_POPUP, 0 );
|
||||||
|
trace( "created owner %p and popup %p\n", owner, test );
|
||||||
|
ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (ULONG_PTR)owner );
|
||||||
|
ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0", ret );
|
||||||
|
check_parents( test, desktop, owner, owner, owner, test, hwndMain2 );
|
||||||
|
DestroyWindow( owner );
|
||||||
|
ok( IsWindow(test), "Window %p destroyed by owner destruction", test );
|
||||||
|
ok( !IsWindow(owner), "Owner %p not destroyed", owner );
|
||||||
|
check_parents( test, desktop, owner, owner, owner, test, owner );
|
||||||
|
DestroyWindow(test);
|
||||||
|
|
||||||
|
/* final cleanup */
|
||||||
|
DestroyWindow(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||||
|
{
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_GETMINMAXINFO:
|
||||||
|
{
|
||||||
|
MINMAXINFO* minmax = (MINMAXINFO *)lparam;
|
||||||
|
|
||||||
|
trace("hwnd %p, WM_GETMINMAXINFO, %08x, %08lx\n", hwnd, wparam, lparam);
|
||||||
|
trace("ptReserved (%ld,%ld), ptMaxSize (%ld,%ld), ptMaxPosition (%ld,%ld)\n"
|
||||||
|
" ptMinTrackSize (%ld,%ld), ptMaxTrackSize (%ld,%ld)\n",
|
||||||
|
minmax->ptReserved.x, minmax->ptReserved.y,
|
||||||
|
minmax->ptMaxSize.x, minmax->ptMaxSize.y,
|
||||||
|
minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
|
||||||
|
minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
|
||||||
|
minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
|
||||||
|
SetWindowLongA(hwnd, GWL_USERDATA, 0x20031021);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_NCCREATE:
|
||||||
|
{
|
||||||
|
BOOL got_getminmaxinfo = GetWindowLongA(hwnd, GWL_USERDATA) == 0x20031021;
|
||||||
|
CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
|
||||||
|
|
||||||
|
trace("WM_NCCREATE: hwnd %p, parent %p, style %08lx\n", hwnd, cs->hwndParent, cs->style);
|
||||||
|
if (got_getminmaxinfo)
|
||||||
|
trace("%p got WM_GETMINMAXINFO\n", hwnd);
|
||||||
|
|
||||||
|
if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
|
||||||
|
ok(got_getminmaxinfo, "main: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
|
||||||
|
else
|
||||||
|
ok(!got_getminmaxinfo, "main: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefWindowProcA(hwnd, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
||||||
|
static LRESULT WINAPI tool_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||||
|
{
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_GETMINMAXINFO:
|
||||||
|
{
|
||||||
|
MINMAXINFO* minmax = (MINMAXINFO *)lparam;
|
||||||
|
|
||||||
|
trace("hwnd %p, WM_GETMINMAXINFO, %08x, %08lx\n", hwnd, wparam, lparam);
|
||||||
|
trace("ptReserved (%ld,%ld), ptMaxSize (%ld,%ld), ptMaxPosition (%ld,%ld)\n"
|
||||||
|
" ptMinTrackSize (%ld,%ld), ptMaxTrackSize (%ld,%ld)\n",
|
||||||
|
minmax->ptReserved.x, minmax->ptReserved.y,
|
||||||
|
minmax->ptMaxSize.x, minmax->ptMaxSize.y,
|
||||||
|
minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
|
||||||
|
minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
|
||||||
|
minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
|
||||||
|
SetWindowLongA(hwnd, GWL_USERDATA, 0x20031021);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_NCCREATE:
|
||||||
|
{
|
||||||
|
BOOL got_getminmaxinfo = GetWindowLongA(hwnd, GWL_USERDATA) == 0x20031021;
|
||||||
|
CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
|
||||||
|
|
||||||
|
trace("WM_NCCREATE: hwnd %p, parent %p, style %08lx\n", hwnd, cs->hwndParent, cs->style);
|
||||||
|
if (got_getminmaxinfo)
|
||||||
|
trace("%p got WM_GETMINMAXINFO\n", hwnd);
|
||||||
|
|
||||||
|
if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
|
||||||
|
ok(got_getminmaxinfo, "tool: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
|
||||||
|
else
|
||||||
|
ok(!got_getminmaxinfo, "tool: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefWindowProcA(hwnd, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL RegisterWindowClasses(void)
|
||||||
|
{
|
||||||
|
WNDCLASSA cls;
|
||||||
|
|
||||||
|
cls.style = 0;
|
||||||
|
cls.lpfnWndProc = main_window_procA;
|
||||||
|
cls.cbClsExtra = 0;
|
||||||
|
cls.cbWndExtra = 0;
|
||||||
|
cls.hInstance = GetModuleHandleA(0);
|
||||||
|
cls.hIcon = 0;
|
||||||
|
cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
|
||||||
|
cls.hbrBackground = GetStockObject(WHITE_BRUSH);
|
||||||
|
cls.lpszMenuName = NULL;
|
||||||
|
cls.lpszClassName = "MainWindowClass";
|
||||||
|
|
||||||
|
if(!RegisterClassA(&cls)) return FALSE;
|
||||||
|
|
||||||
|
cls.style = 0;
|
||||||
|
cls.lpfnWndProc = tool_window_procA;
|
||||||
|
cls.cbClsExtra = 0;
|
||||||
|
cls.cbWndExtra = 0;
|
||||||
|
cls.hInstance = GetModuleHandleA(0);
|
||||||
|
cls.hIcon = 0;
|
||||||
|
cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
|
||||||
|
cls.hbrBackground = GetStockObject(WHITE_BRUSH);
|
||||||
|
cls.lpszMenuName = NULL;
|
||||||
|
cls.lpszClassName = "ToolWindowClass";
|
||||||
|
|
||||||
|
if(!RegisterClassA(&cls)) return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
static const char *CBT_code_name[10] = {
|
||||||
|
"HCBT_MOVESIZE",
|
||||||
|
"HCBT_MINMAX",
|
||||||
|
"HCBT_QS",
|
||||||
|
"HCBT_CREATEWND",
|
||||||
|
"HCBT_DESTROYWND",
|
||||||
|
"HCBT_ACTIVATE",
|
||||||
|
"HCBT_CLICKSKIPPED",
|
||||||
|
"HCBT_KEYSKIPPED",
|
||||||
|
"HCBT_SYSCOMMAND",
|
||||||
|
"HCBT_SETFOCUS" };
|
||||||
|
const char *code_name = (nCode >= 0 && nCode <= HCBT_SETFOCUS) ? CBT_code_name[nCode] : "Unknown";
|
||||||
|
|
||||||
|
trace("CBT: %d (%s), %08x, %08lx\n", nCode, code_name, wParam, lParam);
|
||||||
|
|
||||||
|
switch (nCode)
|
||||||
|
{
|
||||||
|
case HCBT_CREATEWND:
|
||||||
|
{
|
||||||
|
CBT_CREATEWNDA *createwnd = (CBT_CREATEWNDA *)lParam;
|
||||||
|
trace("HCBT_CREATEWND: hwnd %p, parent %p, style %08lx\n",
|
||||||
|
(HWND)wParam, createwnd->lpcs->hwndParent, createwnd->lpcs->style);
|
||||||
|
ok(createwnd->hwndInsertAfter == HWND_TOP, "hwndInsertAfter should be always HWND_TOP\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CallNextHookEx(hhook, nCode, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_shell_window()
|
||||||
|
{
|
||||||
|
BOOL ret;
|
||||||
|
DWORD error;
|
||||||
|
HMODULE hinst, hUser32;
|
||||||
|
BOOL (WINAPI*SetShellWindow)(HWND);
|
||||||
|
BOOL (WINAPI*SetShellWindowEx)(HWND, HWND);
|
||||||
|
HWND hwnd1, hwnd2, hwnd3, hwnd4, hwnd5;
|
||||||
|
HWND shellWindow, nextWnd;
|
||||||
|
|
||||||
|
shellWindow = GetShellWindow();
|
||||||
|
hinst = GetModuleHandle(0);
|
||||||
|
hUser32 = GetModuleHandleA("user32");
|
||||||
|
|
||||||
|
SetShellWindow = (void *)GetProcAddress(hUser32, "SetShellWindow");
|
||||||
|
SetShellWindowEx = (void *)GetProcAddress(hUser32, "SetShellWindowEx");
|
||||||
|
|
||||||
|
trace("previous shell window: %p\n", shellWindow);
|
||||||
|
|
||||||
|
if (shellWindow) {
|
||||||
|
DWORD pid;
|
||||||
|
HANDLE hProcess;
|
||||||
|
|
||||||
|
ret = DestroyWindow(shellWindow);
|
||||||
|
error = GetLastError();
|
||||||
|
|
||||||
|
ok(!ret, "DestroyWindow(shellWindow)\n");
|
||||||
|
/* passes on Win XP, but not on Win98
|
||||||
|
ok(error==ERROR_ACCESS_DENIED, "ERROR_ACCESS_DENIED after DestroyWindow(shellWindow)\n"); */
|
||||||
|
|
||||||
|
/* close old shell instance */
|
||||||
|
GetWindowThreadProcessId(shellWindow, &pid);
|
||||||
|
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
||||||
|
ret = TerminateProcess(hProcess, 0);
|
||||||
|
ok(ret, "termination of previous shell process failed: GetLastError()=%ld", GetLastError());
|
||||||
|
WaitForSingleObject(hProcess, INFINITE); /* wait for termination */
|
||||||
|
CloseHandle(hProcess);
|
||||||
|
}
|
||||||
|
|
||||||
|
hwnd1 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST1"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 100, 100, 300, 200, 0, 0, hinst, 0);
|
||||||
|
trace("created window 1: %p\n", hwnd1);
|
||||||
|
|
||||||
|
ret = SetShellWindow(hwnd1);
|
||||||
|
ok(ret, "first call to SetShellWindow(hwnd1)\n");
|
||||||
|
shellWindow = GetShellWindow();
|
||||||
|
ok(shellWindow==hwnd1, "wrong shell window: %p", shellWindow);
|
||||||
|
|
||||||
|
ret = SetShellWindow(hwnd1);
|
||||||
|
ok(!ret, "second call to SetShellWindow(hwnd1)\n");
|
||||||
|
|
||||||
|
ret = SetShellWindow(0);
|
||||||
|
error = GetLastError();
|
||||||
|
/* passes on Win XP, but not on Win98
|
||||||
|
ok(!ret, "reset shell window by SetShellWindow(0)\n");
|
||||||
|
ok(error==ERROR_INVALID_WINDOW_HANDLE, "ERROR_INVALID_WINDOW_HANDLE after SetShellWindow(0)\n"); */
|
||||||
|
|
||||||
|
ret = SetShellWindow(hwnd1);
|
||||||
|
/* passes on Win XP, but not on Win98
|
||||||
|
ok(!ret, "third call to SetShellWindow(hwnd1)\n"); */
|
||||||
|
|
||||||
|
todo_wine
|
||||||
|
{
|
||||||
|
SetWindowLong(hwnd1, GWL_EXSTYLE, GetWindowLong(hwnd1,GWL_EXSTYLE)|WS_EX_TOPMOST);
|
||||||
|
ret = GetWindowLong(hwnd1,GWL_EXSTYLE)&WS_EX_TOPMOST? TRUE: FALSE;
|
||||||
|
ok(!ret, "SetWindowExStyle(hwnd1, WS_EX_TOPMOST)\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = DestroyWindow(hwnd1);
|
||||||
|
ok(ret, "DestroyWindow(hwnd1)\n");
|
||||||
|
|
||||||
|
hwnd2 = CreateWindowEx(WS_EX_TOPMOST, TEXT("#32770"), TEXT("TEST2"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 150, 250, 300, 200, 0, 0, hinst, 0);
|
||||||
|
trace("created window 2: %p\n", hwnd2);
|
||||||
|
ret = SetShellWindow(hwnd2);
|
||||||
|
ok(!ret, "SetShellWindow(hwnd2) with WS_EX_TOPMOST");
|
||||||
|
|
||||||
|
hwnd3 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST3"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 200, 400, 300, 200, 0, 0, hinst, 0);
|
||||||
|
trace("created window 3: %p\n", hwnd3);
|
||||||
|
|
||||||
|
hwnd4 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST4"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 250, 500, 300, 200, 0, 0, hinst, 0);
|
||||||
|
trace("created window 4: %p\n", hwnd4);
|
||||||
|
|
||||||
|
nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
|
||||||
|
ok(nextWnd==hwnd3, "wrong next window for hwnd4: %p - expected hwnd3\n", nextWnd);
|
||||||
|
|
||||||
|
ret = SetShellWindow(hwnd4);
|
||||||
|
ok(ret, "SetShellWindow(hwnd4)\n");
|
||||||
|
shellWindow = GetShellWindow();
|
||||||
|
ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4", shellWindow);
|
||||||
|
|
||||||
|
nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
|
||||||
|
ok(nextWnd==0, "wrong next window for hwnd4: %p - expected 0\n", nextWnd);
|
||||||
|
|
||||||
|
ret = SetWindowPos(hwnd4, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
|
||||||
|
ok(ret, "SetWindowPos(hwnd4, HWND_TOPMOST)\n");
|
||||||
|
|
||||||
|
ret = SetWindowPos(hwnd4, hwnd3, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
|
||||||
|
ok(ret, "SetWindowPos(hwnd4, hwnd3");
|
||||||
|
|
||||||
|
ret = SetShellWindow(hwnd3);
|
||||||
|
ok(!ret, "SetShellWindow(hwnd3)\n");
|
||||||
|
shellWindow = GetShellWindow();
|
||||||
|
ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4", shellWindow);
|
||||||
|
|
||||||
|
hwnd5 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST5"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 300, 600, 300, 200, 0, 0, hinst, 0);
|
||||||
|
trace("created window 5: %p\n", hwnd5);
|
||||||
|
ret = SetWindowPos(hwnd4, hwnd5, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
|
||||||
|
ok(ret, "SetWindowPos(hwnd4, hwnd5)\n");
|
||||||
|
|
||||||
|
todo_wine
|
||||||
|
{
|
||||||
|
nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
|
||||||
|
ok(nextWnd==0, "wrong next window for hwnd4 after SetWindowPos(): %p - expected 0\n", nextWnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* destroy test windows */
|
||||||
|
DestroyWindow(hwnd2);
|
||||||
|
DestroyWindow(hwnd3);
|
||||||
|
DestroyWindow(hwnd4);
|
||||||
|
DestroyWindow(hwnd5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
START_TEST(win)
|
||||||
|
{
|
||||||
|
pGetAncestor = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetAncestor" );
|
||||||
|
|
||||||
|
if (!RegisterWindowClasses()) assert(0);
|
||||||
|
|
||||||
|
hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
|
||||||
|
assert(hhook);
|
||||||
|
|
||||||
|
hwndMain = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window",
|
||||||
|
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
|
||||||
|
WS_MAXIMIZEBOX | WS_POPUP,
|
||||||
|
100, 100, 200, 200,
|
||||||
|
0, 0, 0, NULL);
|
||||||
|
hwndMain2 = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window 2",
|
||||||
|
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
|
||||||
|
WS_MAXIMIZEBOX | WS_POPUP,
|
||||||
|
100, 100, 200, 200,
|
||||||
|
0, 0, 0, NULL);
|
||||||
|
assert( hwndMain );
|
||||||
|
assert( hwndMain2 );
|
||||||
|
|
||||||
|
test_parent_owner();
|
||||||
|
test_shell_window();
|
||||||
|
UnhookWindowsHookEx(hhook);
|
||||||
|
}
|
57
reactos/apps/tests/user32/wsprintf.c
Normal file
57
reactos/apps/tests/user32/wsprintf.c
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/* Unit test suite for the wsprintf functions
|
||||||
|
*
|
||||||
|
* Copyright 2002 Bill Medland
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "wine/test.h"
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
|
||||||
|
static void wsprintfATest(void)
|
||||||
|
{
|
||||||
|
char buf[25];
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc=wsprintfA(buf, "%010ld", -1);
|
||||||
|
ok(rc == 10, "wsPrintfA length failure: rc=%d error=%ld",rc,GetLastError());
|
||||||
|
ok((lstrcmpA(buf, "-000000001") == 0),
|
||||||
|
"wsprintfA zero padded negative value failure: buf=[%s]",buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wsprintfWTest(void)
|
||||||
|
{
|
||||||
|
static const WCHAR fmt[] = {'%','0','1','0','l','d','\0'};
|
||||||
|
static const WCHAR target[] = {'-','0','0','0','0','0','0','0','0','1', '\0'};
|
||||||
|
WCHAR buf[25];
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc=wsprintfW(buf, fmt, -1);
|
||||||
|
if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
|
||||||
|
return;
|
||||||
|
ok(rc == 10, "wsPrintfW length failure: rc=%d error=%ld",rc,GetLastError());
|
||||||
|
ok((lstrcmpW(buf, target) == 0),
|
||||||
|
"wsprintfW zero padded negative value failure");
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(wsprintf)
|
||||||
|
{
|
||||||
|
wsprintfATest();
|
||||||
|
wsprintfWTest();
|
||||||
|
}
|
Loading…
Reference in a new issue