354 lines
17 KiB
C
354 lines
17 KiB
C
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
#include <windows.h>
|
|
#include <commctrl.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define REVIEW_CONFIG (WM_APP + 10)
|
|
#define REVIEW_CHECK (WM_APP + 11)
|
|
#define REVIEW_CHECK_RIGHT (WM_APP + 12)
|
|
#define REVIEW_CHECK_STRICT (WM_APP + 13)
|
|
#define REVIEW_PRIVACY_CHECK (WM_APP + 14)
|
|
#define REVIEW_REMOTE_CHECK (WM_APP + 15)
|
|
static HWND editor, output, password, hidden;
|
|
static HWND mdi, mdi_active, mdi_background;
|
|
static WCHAR *large;
|
|
static WNDPROC original_edit;
|
|
static BOOL replace_during_read;
|
|
static BOOL stall_accessible;
|
|
static BOOL secondary;
|
|
static unsigned int key_down, key_up;
|
|
static const WCHAR *expected_text = L"alpha beta\r\nsecond line";
|
|
static BOOL protect_during_length, replace_list_during_read;
|
|
static unsigned int protected_text_reads;
|
|
static WNDPROC original_list;
|
|
static WNDPROC original_table;
|
|
static BOOL replace_table_during_read;
|
|
static BOOL delay_table_read, freed_table_memory, scroll_during_position;
|
|
static BOOL frame_pump;
|
|
static BOOL delay_batch;
|
|
static unsigned int synthetic_containers;
|
|
static LRESULT CALLBACK status_proc(HWND window,UINT message,WPARAM wp,LPARAM lp) {
|
|
// Like MUSHclient's status bar, report a length beyond the first NUL.
|
|
// The standard MSAA fallback retains that padding in its BSTR name.
|
|
const WCHAR text[]=L"Ready\0Connected";
|
|
if(message==WM_GETTEXTLENGTH)return (sizeof(text)/sizeof(*text))-1;
|
|
if(message==WM_GETTEXT && wp) {
|
|
size_t copied=(sizeof(text)/sizeof(*text))-1;
|
|
if(copied>wp-1)copied=wp-1;
|
|
memcpy((void*)lp,text,copied*sizeof(*text));
|
|
((WCHAR*)lp)[copied]=0;
|
|
return copied;
|
|
}
|
|
return DefWindowProcW(window,message,wp,lp);
|
|
}
|
|
static LRESULT CALLBACK container_proc(HWND window,UINT message,WPARAM wp,LPARAM lp) {
|
|
if(message==WM_GETOBJECT && lp==OBJID_QUERYCLASSNAMEIDX){++synthetic_containers;Sleep(25);}
|
|
return DefWindowProcW(window,message,wp,lp);
|
|
}
|
|
static LRESULT CALLBACK table_proc(HWND window, UINT message, WPARAM wp, LPARAM lp) {
|
|
if (message == LVM_GETITEMTEXTW && delay_table_read) {
|
|
delay_table_read=FALSE;
|
|
Sleep(650);
|
|
MEMORY_BASIC_INFORMATION memory={0};
|
|
if (!VirtualQuery((void*)lp,&memory,sizeof(memory)) || memory.State != MEM_COMMIT) {
|
|
freed_table_memory=TRUE;
|
|
return 0; // Observe the unsafe lifetime without dereferencing freed data.
|
|
}
|
|
}
|
|
LRESULT result=CallWindowProcW(original_table,window,message,wp,lp);
|
|
if (message == LVM_GETITEMTEXTW && replace_table_during_read) {
|
|
replace_table_during_read=FALSE;
|
|
LVITEMW item={0}; item.pszText=L"other & item";
|
|
SendMessageW(window,LVM_SETITEMTEXTW,0,(LPARAM)&item);
|
|
}
|
|
return result;
|
|
}
|
|
static LRESULT CALLBACK list_proc(HWND window, UINT message, WPARAM wp, LPARAM lp) {
|
|
LRESULT result = CallWindowProcW(original_list,window,message,wp,lp);
|
|
if (message == LB_GETTEXT && replace_list_during_read) {
|
|
replace_list_during_read = FALSE;
|
|
SendMessageW(window,LB_DELETESTRING,0,0);
|
|
SendMessageW(window,LB_INSERTSTRING,0,(LPARAM)L"update & item");
|
|
}
|
|
return result;
|
|
}
|
|
static LRESULT CALLBACK stall_proc(HWND window, UINT message, WPARAM wp, LPARAM lp) {
|
|
if (message == WM_GETOBJECT && stall_accessible) {
|
|
stall_accessible = FALSE;
|
|
Sleep(2000);
|
|
}
|
|
return DefWindowProcW(window,message,wp,lp);
|
|
}
|
|
static LRESULT CALLBACK edit_proc(HWND window, UINT message, WPARAM wp, LPARAM lp) {
|
|
if(message==EM_LINEINDEX && delay_batch){delay_batch=FALSE;Sleep(650);}
|
|
if (message == WM_GETTEXT && (GetWindowLongPtrW(window,GWL_STYLE) & ES_PASSWORD)) ++protected_text_reads;
|
|
if (message == WM_KEYDOWN) ++key_down;
|
|
if (message == WM_KEYUP) ++key_up;
|
|
LRESULT result = CallWindowProcW(original_edit, window, message, wp, lp);
|
|
if (message == WM_GETTEXTLENGTH && protect_during_length) {
|
|
protect_during_length = FALSE;
|
|
SendMessageW(window,EM_SETPASSWORDCHAR,L'*',0);
|
|
}
|
|
if (message == WM_GETTEXT && replace_during_read) {
|
|
replace_during_read = FALSE;
|
|
SetWindowTextW(window, L"omega zeta\r\nsecond line");
|
|
}
|
|
if (message == EM_POSFROMCHAR && scroll_during_position) {
|
|
scroll_during_position=FALSE;
|
|
SendMessageW(window,EM_LINESCROLL,0,1);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static LRESULT CALLBACK window_proc(HWND window, UINT message, WPARAM wp, LPARAM lp) {
|
|
(void)lp;
|
|
if (message == WM_TIMER && secondary) {
|
|
KillTimer(window,1);
|
|
SetForegroundWindow(window);
|
|
SetFocus(GetDlgItem(window,105));
|
|
return 0;
|
|
}
|
|
if (message == REVIEW_CONFIG) {
|
|
frame_pump=FALSE;
|
|
delay_batch=FALSE;
|
|
synthetic_containers=0;
|
|
ShowWindow(GetDlgItem(window,112),SW_HIDE);
|
|
ShowWindow(GetDlgItem(window,114),SW_HIDE);
|
|
ShowWindow(mdi,SW_HIDE);
|
|
SendMessageW(editor,EM_SETPASSWORDCHAR,0,0);
|
|
protect_during_length = replace_list_during_read = FALSE;
|
|
replace_table_during_read=FALSE;
|
|
delay_table_read=freed_table_memory=scroll_during_position=FALSE;
|
|
protected_text_reads = 0;
|
|
key_down = key_up = 0;
|
|
expected_text = L"alpha beta\r\nsecond line";
|
|
ShowWindow(GetDlgItem(window,106),SW_SHOW);
|
|
ShowWindow(GetDlgItem(window,107),SW_HIDE);
|
|
ShowWindow(GetDlgItem(window,109),SW_HIDE);
|
|
ShowWindow(GetDlgItem(window,110),SW_HIDE);
|
|
ShowWindow(GetDlgItem(window,111),SW_HIDE);
|
|
SetWindowTextW(editor, L"alpha beta\r\nsecond line");
|
|
SetWindowTextW(output, L"output first\r\noutput second");
|
|
SendMessageW(editor, EM_SETREADONLY, FALSE, 0);
|
|
SendMessageW(editor, EM_SETSEL, 0, 0);
|
|
MoveWindow(editor, 20, 35, 320, 90, TRUE);
|
|
switch (wp) {
|
|
case 33: ShowWindow(GetDlgItem(window,114),SW_SHOW); break;
|
|
case 32: {
|
|
WCHAR text[16384]; unsigned used = 0;
|
|
for (unsigned row = 0; row < 400; ++row) {
|
|
const WCHAR line[] = L"deep clipped visible line\r\n";
|
|
for (unsigned j = 0; j < (sizeof(line)/sizeof(*line))-1; ++j) text[used++] = line[j];
|
|
}
|
|
text[used] = 0;
|
|
SetWindowTextW(editor, text);
|
|
MoveWindow(editor, 20, -5000, 320, 5100, TRUE);
|
|
break;
|
|
}
|
|
case 30:
|
|
ShowWindow(mdi,SW_SHOW);
|
|
SendMessageW(mdi,WM_MDIACTIVATE,(WPARAM)mdi_active,0);
|
|
SendMessageW(mdi,WM_MDIMAXIMIZE,(WPARAM)mdi_active,0);
|
|
break;
|
|
case 31:
|
|
ShowWindow(mdi,SW_SHOW);
|
|
SendMessageW(mdi,WM_MDIRESTORE,(WPARAM)mdi_active,0);
|
|
SendMessageW(mdi,WM_MDIRESTORE,(WPARAM)mdi_background,0);
|
|
MoveWindow(mdi_background,0,0,240,300,TRUE);
|
|
MoveWindow(mdi_active,245,0,240,300,TRUE);
|
|
SendMessageW(mdi,WM_MDIACTIVATE,(WPARAM)mdi_active,0);
|
|
break;
|
|
case 28: {
|
|
WCHAR text[4096];unsigned used=0;
|
|
for(unsigned row=0;row<80;++row) {
|
|
const WCHAR line[]=L"top clipped visible line\r\n";
|
|
for(unsigned j=0;j<(sizeof(line)/sizeof(*line))-1;++j)text[used++]=line[j];
|
|
}
|
|
text[used]=0;SetWindowTextW(editor,text);
|
|
MoveWindow(editor,20,-250,320,380,TRUE);
|
|
break;
|
|
}
|
|
case 29:ShowWindow(GetDlgItem(window,112),SW_SHOW);break;
|
|
case 27:delay_batch=TRUE;break;
|
|
case 26: {
|
|
WCHAR text[4096];unsigned used=0;
|
|
for(unsigned row=0;row<80;++row) {
|
|
const WCHAR line[]=L"stable buffered output line\r\n";
|
|
for(unsigned j=0;j<(sizeof(line)/sizeof(*line))-1;++j)text[used++]=line[j];
|
|
}
|
|
text[used]=0;SetWindowTextW(editor,text);
|
|
MoveWindow(editor,20,35,320,380,TRUE);
|
|
ShowWindow(output,SW_HIDE);ShowWindow(GetDlgItem(window,106),SW_HIDE);
|
|
frame_pump=TRUE;
|
|
break;
|
|
}
|
|
case 1: // surrogate before first displayed row, absolute offsets
|
|
SetWindowTextW(editor, L"\U0001f600alpha\r\nbeta\r\nlast");
|
|
SendMessageW(editor, EM_LINESCROLL, 0, 1);
|
|
break;
|
|
case 2:
|
|
SetWindowTextW(editor, L"wrapped words repeated wrapped words repeated wrapped words repeated wrapped words\r\n\r\nlast");
|
|
MoveWindow(editor, 20, 35, 150, 150, TRUE);
|
|
break;
|
|
case 3: SetWindowTextW(editor, L""); break;
|
|
case 4:
|
|
SetForegroundWindow(window);
|
|
SetFocus(password);
|
|
return 1;
|
|
case 5:
|
|
MoveWindow(editor, 500, 35, 320, 90, TRUE);
|
|
break;
|
|
case 6: expected_text = L"omega zeta\r\nsecond line"; SetWindowTextW(editor, expected_text); break;
|
|
case 7:
|
|
large = malloc(1000002 * sizeof(WCHAR));
|
|
if (!large) ExitProcess(3);
|
|
// Avoid quadratic native wrapping work in the fixture itself.
|
|
for (int i = 0; i < 1000001; ++i) large[i] = i % 32 == 31 ? L'\n' : L'x';
|
|
large[1000001] = 0;
|
|
SendMessageW(editor, EM_LIMITTEXT, 2000000, 0);
|
|
SetWindowTextW(editor, large);
|
|
free(large); large = NULL;
|
|
break;
|
|
case 8: SetWindowPos(window, NULL, -20, -20, 0, 0, SWP_NOSIZE | SWP_NOZORDER); break;
|
|
case 9: replace_during_read = TRUE; break;
|
|
case 10: stall_accessible = TRUE; break;
|
|
case 11:
|
|
SetForegroundWindow(window);
|
|
SetFocus(output);
|
|
return 1;
|
|
case 12: ShowWindow(GetDlgItem(window,106),SW_HIDE); break;
|
|
case 14: protect_during_length = TRUE; break;
|
|
case 15: replace_list_during_read = TRUE; break;
|
|
case 17: ShowWindow(GetDlgItem(window,107),SW_SHOW); break;
|
|
case 18: ShowWindow(GetDlgItem(window,107),SW_SHOW); replace_table_during_read=TRUE; break;
|
|
case 21: ShowWindow(GetDlgItem(window,107),SW_SHOW); delay_table_read=TRUE; break;
|
|
case 22:
|
|
ShowWindow(GetDlgItem(window,109),SW_SHOW);
|
|
SendMessageW(GetDlgItem(window,109),EM_SETSEL,INT_MAX,INT_MAX);
|
|
SendMessageW(GetDlgItem(window,109),EM_SCROLLCARET,0,0);
|
|
break;
|
|
case 23:
|
|
SetWindowTextW(editor,L"first\r\nsecond\r\nthird\r\nfourth\r\nfifth\r\nsixth\r\nseventh\r\neighth\r\nninth\r\ntenth");
|
|
scroll_during_position=TRUE;
|
|
break;
|
|
case 24:
|
|
ShowWindow(GetDlgItem(window,110),SW_SHOW);
|
|
SendMessageW(GetDlgItem(window,110),EM_SETSEL,INT_MAX,INT_MAX);
|
|
SendMessageW(GetDlgItem(window,110),EM_SCROLLCARET,0,0);
|
|
break;
|
|
case 25: ShowWindow(GetDlgItem(window,111),SW_SHOW); break;
|
|
}
|
|
SetForegroundWindow(window);
|
|
SetFocus(editor);
|
|
return 1;
|
|
}
|
|
if (message == REVIEW_PRIVACY_CHECK) return protected_text_reads == 0;
|
|
if (message == WM_APP+16) return synthetic_containers==0;
|
|
if (message == REVIEW_REMOTE_CHECK) return !freed_table_memory;
|
|
if (message == REVIEW_CHECK || message == REVIEW_CHECK_RIGHT || message == REVIEW_CHECK_STRICT) {
|
|
DWORD start = 0, end = 0;
|
|
SendMessageW(editor, EM_GETSEL, (WPARAM)&start, (LPARAM)&end);
|
|
if (message == REVIEW_CHECK) return start == 0 && end == 0 && GetFocus() == editor;
|
|
WCHAR text[128], output_text[128];
|
|
GetWindowTextW(editor,text,128); GetWindowTextW(output,output_text,128);
|
|
if (message == REVIEW_CHECK_RIGHT)
|
|
return start == 1 && end == 1 && key_down == 1 && key_up == 1 && GetFocus() == editor && lstrcmpW(text,expected_text) == 0;
|
|
return start == 0 && end == 0 && GetFocus() == editor && key_down == 0 && key_up == 0 &&
|
|
lstrcmpW(text,expected_text) == 0 && lstrcmpW(output_text,L"output first\r\noutput second") == 0;
|
|
}
|
|
if (message == WM_CLOSE) { DestroyWindow(window); return 0; }
|
|
if (message == WM_DESTROY) { PostQuitMessage(0); return 0; }
|
|
return DefWindowProcW(window, message, wp, lp);
|
|
}
|
|
|
|
int WINAPI WinMain(HINSTANCE instance, HINSTANCE previous, LPSTR args, int show) {
|
|
(void)previous; (void)show;
|
|
secondary=strcmp(args,"--secondary")==0;
|
|
if (strncmp(args,"--configure ",12)==0 || strcmp(args,"--check")==0 || strcmp(args,"--check-strict")==0 || strcmp(args,"--check-right")==0 || strcmp(args,"--check-remote")==0 || strcmp(args,"--close")==0) {
|
|
HWND target=FindWindowW(L"WineAccessReviewFixture",NULL);
|
|
if (!target) return 3;
|
|
if (strcmp(args,"--close")==0) { PostMessageW(target,WM_CLOSE,0,0); return 0; }
|
|
DWORD_PTR result=0;
|
|
UINT message=strcmp(args,"--check")==0 ? REVIEW_CHECK : strcmp(args,"--check-strict")==0 ? REVIEW_CHECK_STRICT : strcmp(args,"--check-right")==0 ? REVIEW_CHECK_RIGHT : strcmp(args,"--check-remote")==0 ? REVIEW_REMOTE_CHECK : REVIEW_CONFIG;
|
|
WPARAM mode=message==REVIEW_CONFIG ? (WPARAM)atoi(args+12) : 0;
|
|
if (!SendMessageTimeoutW(target,message,mode,0,SMTO_ABORTIFHUNG,3000,&result)) return 4;
|
|
return result ? 0 : 5;
|
|
}
|
|
WNDCLASSW cls = {0};
|
|
cls.hInstance = instance; cls.lpfnWndProc = window_proc;
|
|
cls.lpszClassName = secondary ? L"WineAccessReviewSecondary" : L"WineAccessReviewFixture";
|
|
cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
|
RegisterClassW(&cls);
|
|
WNDCLASSW stall=cls; stall.lpszClassName=L"WineReviewStall"; stall.lpfnWndProc=stall_proc;
|
|
RegisterClassW(&stall);
|
|
HWND window = CreateWindowW(cls.lpszClassName, secondary ? L"Wine secondary fixture" : L"Wine review fixture",
|
|
WS_OVERLAPPEDWINDOW, 100, 100, 560, 500, NULL, NULL, instance, NULL);
|
|
CreateWindowW(L"Static", L"&Command:", WS_CHILD | WS_VISIBLE, 20, 10, 200, 20,
|
|
window, NULL, instance, NULL);
|
|
editor = CreateWindowW(L"Edit", L"", WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER |
|
|
ES_MULTILINE | ES_AUTOVSCROLL | WS_VSCROLL, 20, 35, 320, 90, window, (HMENU)101, instance, NULL);
|
|
original_edit = (WNDPROC)SetWindowLongPtrW(editor, GWLP_WNDPROC, (LONG_PTR)edit_proc);
|
|
output = CreateWindowW(L"Edit", L"output first\r\noutput second", WS_CHILD | WS_VISIBLE |
|
|
ES_MULTILINE | ES_READONLY | WS_BORDER, 20, 205, 320, 80, window, (HMENU)102, instance, NULL);
|
|
password = CreateWindowW(L"Edit", L"private-review-secret", WS_CHILD | WS_VISIBLE |
|
|
ES_PASSWORD | WS_BORDER, 20, 320, 200, 25, window, (HMENU)103, instance, NULL);
|
|
hidden = CreateWindowW(L"Static", L"hidden-review-secret", WS_CHILD, 20, 350, 200, 25,
|
|
window, (HMENU)104, instance, NULL);
|
|
CreateWindowW(L"Button", L"&Open && close", WS_CHILD | WS_VISIBLE, 20, 390, 160, 25,
|
|
window, (HMENU)105, instance, NULL);
|
|
HWND list = CreateWindowW(L"ListBox", L"", WS_CHILD | WS_VISIBLE | LBS_NOTIFY,
|
|
350, 35, 150, 70, window, (HMENU)106, instance, NULL);
|
|
original_list = (WNDPROC)SetWindowLongPtrW(list,GWLP_WNDPROC,(LONG_PTR)list_proc);
|
|
SendMessageW(list, LB_ADDSTRING, 0, (LPARAM)L"native & item");
|
|
SendMessageW(list, LB_ADDSTRING, 0, (LPARAM)L"another item");
|
|
INITCOMMONCONTROLSEX controls = {sizeof(controls), ICC_LISTVIEW_CLASSES};
|
|
InitCommonControlsEx(&controls);
|
|
HWND table = CreateWindowW(WC_LISTVIEWW,L"",WS_CHILD|LVS_REPORT,
|
|
350,200,170,100,window,(HMENU)107,instance,NULL);
|
|
LVCOLUMNW column = {0}; column.mask=LVCF_TEXT|LVCF_WIDTH; column.cx=100; column.pszText=L"Plugin";
|
|
SendMessageW(table,LVM_INSERTCOLUMNW,0,(LPARAM)&column);
|
|
column.cx=60; column.pszText=L"State";
|
|
SendMessageW(table,LVM_INSERTCOLUMNW,1,(LPARAM)&column);
|
|
LVITEMW item={0}; item.mask=LVIF_TEXT; item.pszText=L"table & item";
|
|
SendMessageW(table,LVM_INSERTITEMW,0,(LPARAM)&item);
|
|
item.iSubItem=1; item.pszText=L"ready";
|
|
SendMessageW(table,LVM_SETITEMTEXTW,0,(LPARAM)&item);
|
|
original_table=(WNDPROC)SetWindowLongPtrW(table,GWLP_WNDPROC,(LONG_PTR)table_proc);
|
|
CreateWindowW(L"Edit",L"abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz visible suffix",
|
|
WS_CHILD|ES_AUTOHSCROLL|WS_BORDER,20,130,150,25,window,(HMENU)109,instance,NULL);
|
|
CreateWindowW(L"Edit",L"abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz visible suffix",
|
|
WS_CHILD|ES_MULTILINE|ES_AUTOHSCROLL|WS_HSCROLL|WS_BORDER,20,165,150,50,window,(HMENU)110,instance,NULL);
|
|
CreateWindowW(L"Static",L"literal & label",WS_CHILD|SS_NOPREFIX,
|
|
20,365,200,20,window,(HMENU)111,instance,NULL);
|
|
CreateWindowW(stall.lpszClassName,L"",WS_CHILD|WS_VISIBLE,350,150,150,20,window,NULL,instance,NULL);
|
|
WNDCLASSW container={0};container.lpfnWndProc=container_proc;container.hInstance=instance;container.lpszClassName=L"WineAccessNativeContainer";
|
|
RegisterClassW(&container);
|
|
HWND parent=CreateWindowW(container.lpszClassName,L"",WS_CHILD,20,35,320,100,window,(HMENU)112,instance,NULL);
|
|
for(unsigned level=0;level<8;++level)parent=CreateWindowW(container.lpszClassName,L"",WS_CHILD|WS_VISIBLE,0,0,320,100,parent,NULL,instance,NULL);
|
|
CreateWindowW(L"Edit",L"nested output ready",WS_CHILD|WS_VISIBLE|ES_READONLY,0,0,320,80,parent,NULL,instance,NULL);
|
|
WNDCLASSW mdi_child={0};mdi_child.lpfnWndProc=DefMDIChildProcW;mdi_child.hInstance=instance;mdi_child.lpszClassName=L"WineAccessMdiChild";
|
|
RegisterClassW(&mdi_child);
|
|
CLIENTCREATESTRUCT client_create={NULL,200};
|
|
mdi=CreateWindowW(L"MDIClient",L"",WS_CHILD|WS_CLIPCHILDREN,20,35,500,350,window,(HMENU)113,instance,&client_create);
|
|
mdi_background=CreateMDIWindowW(mdi_child.lpszClassName,L"Background",WS_OVERLAPPEDWINDOW|WS_VISIBLE,0,0,240,300,mdi,instance,0);
|
|
CreateWindowW(L"Edit",L"covered mdi text",WS_CHILD|WS_VISIBLE|ES_READONLY,0,0,220,100,mdi_background,NULL,instance,NULL);
|
|
mdi_active=CreateMDIWindowW(mdi_child.lpszClassName,L"Active",WS_OVERLAPPEDWINDOW|WS_VISIBLE,245,0,240,300,mdi,instance,0);
|
|
CreateWindowW(L"Edit",L"active mdi text",WS_CHILD|WS_VISIBLE|ES_READONLY,0,0,220,100,mdi_active,NULL,instance,NULL);
|
|
WNDCLASSW status=cls;status.lpszClassName=L"WineAccessStatusFixture";status.lpfnWndProc=status_proc;
|
|
RegisterClassW(&status);
|
|
CreateWindowW(status.lpszClassName,L"",WS_CHILD,20,420,480,20,window,(HMENU)114,instance,NULL);
|
|
ShowWindow(window, SW_SHOW);
|
|
SendMessageW(window, REVIEW_CONFIG, 0, 0);
|
|
if (secondary) SetTimer(window,1,400,NULL);
|
|
MSG message;
|
|
for (;;) {
|
|
if (frame_pump) {
|
|
if (!PeekMessageW(&message,NULL,0,0,PM_REMOVE)) { Sleep(16);continue; }
|
|
if (message.message==WM_QUIT)break;
|
|
} else if (GetMessageW(&message,NULL,0,0)<=0)break;
|
|
TranslateMessage(&message); DispatchMessageW(&message);
|
|
}
|
|
return 0;
|
|
}
|