partly implemented the mixer selection dialog Modified: trunk/reactos/subsys/system/sndvol32/Cz.rc Modified: trunk/reactos/subsys/system/sndvol32/De.rc Modified: trunk/reactos/subsys/system/sndvol32/En.rc Modified: trunk/reactos/subsys/system/sndvol32/Fr.rc Modified: trunk/reactos/subsys/system/sndvol32/mixer.c Modified: trunk/reactos/subsys/system/sndvol32/resources.h Modified: trunk/reactos/subsys/system/sndvol32/sndvol32.c Modified: trunk/reactos/subsys/system/sndvol32/sndvol32.h Modified: trunk/reactos/subsys/system/sndvol32/sndvol32.xml _____
Modified: trunk/reactos/subsys/system/sndvol32/Cz.rc --- trunk/reactos/subsys/system/sndvol32/Cz.rc 2005-09-27 00:46:19 UTC (rev 18114) +++ trunk/reactos/subsys/system/sndvol32/Cz.rc 2005-09-27 01:02:15 UTC (rev 18115) @@ -35,6 +35,8 @@
PUSHBUTTON "&Zßznam", IDC_RECORDING, 13,61,47,8, BS_AUTORADIOBUTTON PUSHBUTTON "&JinÚ:", IDC_OTHER, 13,80,42,8, BS_AUTORADIOBUTTON | WS_DISABLED COMBOBOX IDC_LINE, 55,80,155,50, CBS_DROPDOWNLIST | WS_TABSTOP | WS_DISABLED + LTEXT "Show the following volume controls:", IDC_LABELCONTROLS, 7, 109, 162, 8 + CONTROL "", IDC_CONTROLS, "SysListView32", LVS_REPORT | LVS_NOCOLUMNHEADER | WS_TABSTOP | WS_BORDER, 7, 122, 211, 96
PUSHBUTTON "OK", IDOK, 114,226,50,14 PUSHBUTTON "ZruÜit", IDCANCEL, 168,226,50,14 _____
Modified: trunk/reactos/subsys/system/sndvol32/De.rc --- trunk/reactos/subsys/system/sndvol32/De.rc 2005-09-27 00:46:19 UTC (rev 18114) +++ trunk/reactos/subsys/system/sndvol32/De.rc 2005-09-27 01:02:15 UTC (rev 18115) @@ -35,6 +35,8 @@
PUSHBUTTON "&Aufnahme", IDC_RECORDING, 13,61,47,8, BS_AUTORADIOBUTTON PUSHBUTTON "A&ndere:", IDC_OTHER, 13,80,42,8, BS_AUTORADIOBUTTON | WS_DISABLED COMBOBOX IDC_LINE, 55,80,155,50, CBS_DROPDOWNLIST | WS_TABSTOP | WS_DISABLED + LTEXT "Show the following volume controls:", IDC_LABELCONTROLS, 7, 109, 162, 8 + CONTROL "", IDC_CONTROLS, "SysListView32", LVS_REPORT | LVS_NOCOLUMNHEADER | WS_TABSTOP | WS_BORDER, 7, 122, 211, 96
PUSHBUTTON "OK", IDOK, 114,226,50,14 PUSHBUTTON "Abbrechen", IDCANCEL, 168,226,50,14 _____
Modified: trunk/reactos/subsys/system/sndvol32/En.rc --- trunk/reactos/subsys/system/sndvol32/En.rc 2005-09-27 00:46:19 UTC (rev 18114) +++ trunk/reactos/subsys/system/sndvol32/En.rc 2005-09-27 01:02:15 UTC (rev 18115) @@ -35,6 +35,8 @@
PUSHBUTTON "&Recording", IDC_RECORDING, 13,61,47,8, BS_AUTORADIOBUTTON PUSHBUTTON "&Other:", IDC_OTHER, 13,80,42,8, BS_AUTORADIOBUTTON | WS_DISABLED COMBOBOX IDC_LINE, 55,80,155,50, CBS_DROPDOWNLIST | WS_TABSTOP | WS_DISABLED + LTEXT "Show the following volume controls:", IDC_LABELCONTROLS, 7, 109, 162, 8 + CONTROL "", IDC_CONTROLS, "SysListView32", LVS_REPORT | LVS_NOCOLUMNHEADER | WS_TABSTOP | WS_BORDER, 7, 122, 211, 96
PUSHBUTTON "OK", IDOK, 114,226,50,14 PUSHBUTTON "Cancel", IDCANCEL, 168,226,50,14 _____
Modified: trunk/reactos/subsys/system/sndvol32/Fr.rc --- trunk/reactos/subsys/system/sndvol32/Fr.rc 2005-09-27 00:46:19 UTC (rev 18114) +++ trunk/reactos/subsys/system/sndvol32/Fr.rc 2005-09-27 01:02:15 UTC (rev 18115) @@ -35,6 +35,8 @@
PUSHBUTTON "&Enregistrement", IDC_RECORDING, 13,61,47,8, BS_AUTORADIOBUTTON PUSHBUTTON "&Autre :", IDC_OTHER, 13,80,42,8, BS_AUTORADIOBUTTON | WS_DISABLED COMBOBOX IDC_LINE, 55,80,155,50, CBS_DROPDOWNLIST | WS_TABSTOP | WS_DISABLED + LTEXT "Show the following volume controls:", IDC_LABELCONTROLS, 7, 109, 162, 8 + CONTROL "", IDC_CONTROLS, "SysListView32", LVS_REPORT | LVS_NOCOLUMNHEADER | WS_TABSTOP | WS_BORDER, 7, 122, 211, 96
PUSHBUTTON "OK", IDOK, 114,226,50,14 PUSHBUTTON "Annuler", IDCANCEL, 168,226,50,14 _____
Modified: trunk/reactos/subsys/system/sndvol32/mixer.c --- trunk/reactos/subsys/system/sndvol32/mixer.c 2005-09-27 00:46:19 UTC (rev 18114) +++ trunk/reactos/subsys/system/sndvol32/mixer.c 2005-09-27 01:02:15 UTC (rev 18115) @@ -117,11 +117,12 @@
if (LineInfo->cControls > 0) { *Controls = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, + 0, LineInfo->cControls * sizeof(MIXERCONTROL)); if (*Controls != NULL) { MIXERLINECONTROLS LineControls; + MMRESULT Result; UINT j;
LineControls.cbStruct = sizeof(LineControls); @@ -130,18 +131,14 @@ LineControls.cbmxctrl = sizeof(MIXERCONTROL); LineControls.pamxctrl = (PVOID)(*Controls);
- for (j = 0; j < LineInfo->cControls; j++) + Result = mixerGetLineControls((HMIXEROBJ)Mixer->hmx, + &LineControls, + MIXER_GETLINECONTROLSF_ALL); + if (Result == MMSYSERR_NOERROR) { - (*Controls)[j].cbStruct = sizeof(MIXERCONTROL); - } - - if (mixerGetLineControls((HMIXEROBJ)Mixer->hmx, - &LineControls, - MIXER_GETLINECONTROLSF_ALL) == MMSYSERR_NOERROR) - { - for (j = 0; j < LineInfo->cControls; j++) + for (j = 0; j < LineControls.cControls; j++) { - DPRINT("Line control: %ws", (*Controls)[j].szName); + DPRINT("Line control: %ws\n", (*Controls)[j].szName); }
return TRUE; @@ -152,12 +149,12 @@ 0, *Controls); *Controls = NULL; - DPRINT("Failed to get line controls!\n"); + DPRINT("Failed to get line (ID: 0x%x) controls: %d\n", LineInfo->dwLineID, Result); } } else { - DPRINT("Failed to allocate memory for %d line controls!\n", LineInfo->cControls); + DPRINT("Failed to allocate memory for %d line (ID: 0x%x) controls!\n", LineInfo->dwLineID, LineInfo->cControls); }
return FALSE; @@ -174,19 +171,23 @@ { UINT i; MIXERLINE LineInfo; + MMRESULT Result; BOOL Ret = TRUE;
LineInfo.cbStruct = sizeof(LineInfo); - LineInfo.dwDestination = Line->Info.dwDestination; for (i = Line->Info.cConnections; i > 0; i--) { + LineInfo.dwDestination = Line->Info.dwDestination; LineInfo.dwSource = i - 1; - if (mixerGetLineInfo((HMIXEROBJ)Mixer->hmx, - &LineInfo, - MIXER_GETLINEINFOF_SOURCE) == MMSYSERR_NOERROR) + Result = mixerGetLineInfo((HMIXEROBJ)Mixer->hmx, + &LineInfo, + MIXER_GETLINEINFOF_SOURCE); + if (Result == MMSYSERR_NOERROR) { LPMIXERCONTROL Controls; PSND_MIXER_CONNECTION Con; + + DPRINT("++ Source: %ws\n", LineInfo.szName);
if (!SndMixerQueryControls(Mixer, &LineInfo, @@ -216,7 +217,7 @@ } else { - DPRINT("Failed to get connection information!\n"); + DPRINT("Failed to get connection information: %d\n", Result); Ret = FALSE; break; } @@ -246,6 +247,8 @@ &Line->Info, MIXER_GETLINEINFOF_DESTINATION) == MMSYSERR_NOERROR) { + DPRINT("+ Destination: %ws (%d)\n", Line->Info.szName, Line->Info.dwComponentType); + if (!SndMixerQueryConnections(Mixer, Line)) { DPRINT("Failed to query mixer connections!\n"); @@ -445,3 +448,38 @@ return FALSE; }
+BOOL +SndMixerEnumConnections(PSND_MIXER Mixer, + DWORD LineID, + PFNSNDMIXENUMCONNECTIONS EnumProc, + PVOID Context) +{ + if (Mixer->hmx) + { + PSND_MIXER_DESTINATION Line; + + for (Line = Mixer->Lines; Line != NULL; Line = Line->Next) + { + if (Line->Info.dwLineID == LineID) + { + PSND_MIXER_CONNECTION Connection; + + for (Connection = Line->Connections; Connection != NULL; Connection = Connection->Next) + { + if (!EnumProc(Mixer, + LineID, + &Connection->Info, + Context)) + { + return FALSE; + } + } + + return TRUE; + } + } + } + + return FALSE; +} + _____
Modified: trunk/reactos/subsys/system/sndvol32/resources.h --- trunk/reactos/subsys/system/sndvol32/resources.h 2005-09-27 00:46:19 UTC (rev 18114) +++ trunk/reactos/subsys/system/sndvol32/resources.h 2005-09-27 01:02:15 UTC (rev 18115) @@ -17,6 +17,8 @@
#define IDC_RECORDING 1003 #define IDC_OTHER 1004 #define IDC_LINE 1005 +#define IDC_LABELCONTROLS 1006 +#define IDC_CONTROLS 1007
#define IDS_SNDVOL32 100 #define IDS_NOMIXERDEVICES 101 _____
Modified: trunk/reactos/subsys/system/sndvol32/sndvol32.c --- trunk/reactos/subsys/system/sndvol32/sndvol32.c 2005-09-27 00:46:19 UTC (rev 18114) +++ trunk/reactos/subsys/system/sndvol32/sndvol32.c 2005-09-27 01:02:15 UTC (rev 18115) @@ -31,6 +31,7 @@
ATOM MainWindowClass; HWND hMainWnd; HANDLE hAppHeap; +LPTSTR lpAppTitle;
#define GetDialogData(hwndDlg, type) \ ( P##type )GetWindowLongPtr((hwndDlg), DWLP_USER) @@ -44,6 +45,12 @@ PMIXER_WINDOW MixerWindow; PSND_MIXER Mixer; HWND hwndDlg; + + UINT Selected; + DWORD SelectedLine; + DWORD PlaybackID; + DWORD RecordingID; + UINT OtherLines; } PREFERENCES_CONTEXT, *PPREFERENCES_CONTEXT;
typedef struct _PREFERENCES_FILL_DEVICES @@ -86,6 +93,209 @@ return TRUE; }
+static BOOL CALLBACK +PrefDlgAddLine(PSND_MIXER Mixer, + LPMIXERLINE Line, + PVOID Context) +{ + PPREFERENCES_CONTEXT PrefContext = (PPREFERENCES_CONTEXT)Context; + + switch (Line->dwComponentType) + { + case MIXERLINE_COMPONENTTYPE_DST_SPEAKERS: + if (PrefContext->PlaybackID == (DWORD)-1) + { + PrefContext->PlaybackID = Line->dwLineID; + + if (PrefContext->SelectedLine == (DWORD)-1) + { + PrefContext->SelectedLine = Line->dwLineID; + } + } + else + goto AddToOthersLines; + + break; + + case MIXERLINE_COMPONENTTYPE_DST_WAVEIN: + if (PrefContext->RecordingID == (DWORD)-1) + { + PrefContext->RecordingID = Line->dwLineID; + + if (PrefContext->SelectedLine == (DWORD)-1) + { + PrefContext->SelectedLine = Line->dwLineID; + } + } + else + goto AddToOthersLines; + + break; + + default: + { + LRESULT lres; + HWND hwndCbOthers; + + if (PrefContext->SelectedLine == (DWORD)-1) + { + PrefContext->SelectedLine = Line->dwLineID; + } + +AddToOthersLines: + hwndCbOthers = GetDlgItem(PrefContext->hwndDlg, + IDC_LINE); + + lres = SendMessage(hwndCbOthers, + CB_ADDSTRING, + 0, + (LPARAM)Line->szName); + if (lres != CB_ERR) + { + SendMessage(hwndCbOthers, + CB_SETITEMDATA, + (WPARAM)lres, + Line->dwLineID); + + PrefContext->OtherLines++; + } + break; + } + } + + return TRUE; +} + +static BOOL CALLBACK +PrefDlgAddConnection(PSND_MIXER Mixer, + DWORD LineID, + LPMIXERLINE Line, + PVOID Context) +{ + PPREFERENCES_CONTEXT PrefContext = (PPREFERENCES_CONTEXT)Context; + LVITEM lvi; + + lvi.mask = LVIF_TEXT | LVIF_PARAM; + lvi.iItem = 0; + lvi.iSubItem = 0; + lvi.pszText = Line->szName; + lvi.lParam = (LPARAM)Line->dwSource; + + SendMessage(GetDlgItem(PrefContext->hwndDlg, + IDC_CONTROLS), + LVM_INSERTITEM, + 0, + (LPARAM)&lvi); + + return TRUE; +} + +static VOID +UpdatePrefDlgControls(PPREFERENCES_CONTEXT Context, + DWORD LineID) +{ + UINT OldID, MixerID = 0; + INT DeviceCbIndex; + + /* select the mixer */ + DeviceCbIndex = SendMessage(GetDlgItem(Context->hwndDlg, + IDC_MIXERDEVICE), + CB_GETCURSEL, + 0, + 0); + if (DeviceCbIndex != CB_ERR) + { + MixerID = SendMessage(GetDlgItem(Context->hwndDlg, + IDC_MIXERDEVICE), + CB_GETITEMDATA, + DeviceCbIndex, + 0); + if (MixerID == CB_ERR) + { + MixerID = 0; + } + } + + OldID = Context->Selected; + if (MixerID != OldID && + SndMixerSelect(Context->Mixer, + MixerID)) + { + Context->Selected = SndMixerGetSelection(Context->Mixer); + + /* update the controls */ + Context->PlaybackID = (DWORD)-1; + Context->RecordingID = (DWORD)-1; + Context->OtherLines = 0; + Context->SelectedLine = (DWORD)-1; + + if (SndMixerEnumLines(Context->Mixer, + PrefDlgAddLine, + Context)) + { + UINT SelBox = 0; + + /* enable/disable controls and make default selection */ + EnableWindow(GetDlgItem(Context->hwndDlg, + IDC_PLAYBACK), + Context->PlaybackID != (DWORD)-1); + CheckDlgButton(Context->hwndDlg, + IDC_PLAYBACK, + (Context->PlaybackID != (DWORD)-1 && SelBox++ == 0) ? + BST_CHECKED : BST_UNCHECKED); + + EnableWindow(GetDlgItem(Context->hwndDlg, + IDC_RECORDING), + Context->RecordingID != (DWORD)-1); + CheckDlgButton(Context->hwndDlg, + IDC_RECORDING, + (Context->RecordingID != (DWORD)-1 && SelBox++ == 0) ? + BST_CHECKED : BST_UNCHECKED); + + if (Context->OtherLines != 0) + { + /* select the first item in the other lines combo box by default */ + SendMessage(GetDlgItem(Context->hwndDlg, + IDC_LINE), + CB_SETCURSEL, + 0, + 0); + } + EnableWindow(GetDlgItem(Context->hwndDlg, + IDC_LINE), + Context->OtherLines != 0); + CheckDlgButton(Context->hwndDlg, + IDC_LINE, + (Context->OtherLines != 0 && SelBox++ == 0) ? + BST_CHECKED : BST_UNCHECKED); + + /* disable the OK button if the device doesn't have any lines */ + EnableWindow(GetDlgItem(Context->hwndDlg, + IDOK), + Context->PlaybackID != (DWORD)-1 || + Context->RecordingID != (DWORD)-1 || + Context->OtherLines != 0); + + LineID = Context->SelectedLine; + } + } + + /* update the line sources list */ + if ((MixerID != OldID && Context->SelectedLine != (DWORD)-1) || + (Context->SelectedLine != LineID && LineID != (DWORD)-1)) + { + Context->SelectedLine = LineID; + + ListView_DeleteAllItems(GetDlgItem(Context->hwndDlg, + IDC_CONTROLS)); + + SndMixerEnumConnections(Context->Mixer, + LineID, + PrefDlgAddConnection, + Context); + } +} + static INT_PTR CALLBACK DlgPreferencesProc(HWND hwndDlg, UINT uMsg, @@ -98,8 +308,70 @@ { case WM_COMMAND: { + Context = GetDialogData(hwndDlg, + PREFERENCES_CONTEXT); switch (LOWORD(wParam)) { + case IDC_MIXERDEVICE: + { + if (HIWORD(wParam) == CBN_SELCHANGE) + { + UpdatePrefDlgControls(Context, + (DWORD)-1); + } + break; + } + + case IDC_LINE: + { + if (HIWORD(wParam) == CBN_SELCHANGE) + { + UpdatePrefDlgControls(Context, + (DWORD)-1); + } + break; + } + + case IDC_PLAYBACK: + { + UpdatePrefDlgControls(Context, + Context->PlaybackID); + break; + } + + case IDC_RECORDING: + { + UpdatePrefDlgControls(Context, + Context->RecordingID); + break; + } + + case IDC_OTHER: + { + INT LineCbIndex; + DWORD LineID; + + LineCbIndex = SendMessage(GetDlgItem(Context->hwndDlg, + IDC_MIXERDEVICE), + CB_GETCURSEL, + 0, + 0); + if (LineCbIndex != CB_ERR) + { + LineID = SendMessage(GetDlgItem(Context->hwndDlg, + IDC_MIXERDEVICE), + CB_GETITEMDATA, + LineCbIndex, + 0); + if (LineID != CB_ERR) + { + UpdatePrefDlgControls(Context, + LineID); + } + } + break; + } + case IDOK: case IDCANCEL: { @@ -126,6 +398,9 @@ case WM_INITDIALOG: { PREFERENCES_FILL_DEVICES FillDevContext; + LVCOLUMN lvc; + RECT rcClient; + HWND hwndControls;
SetWindowLongPtr(hwndDlg, DWLP_USER, @@ -133,6 +408,7 @@ Context = (PPREFERENCES_CONTEXT)((LONG_PTR)lParam); Context->hwndDlg = hwndDlg; Context->Mixer = SndMixerCreate(hwndDlg); + Context->Selected = (UINT)-1;
FillDevContext.PrefContext = Context; FillDevContext.hComboBox = GetDlgItem(hwndDlg, @@ -141,6 +417,26 @@ SndMixerEnumProducts(Context->Mixer, FillDeviceComboBox, &FillDevContext); + + /* initialize the list view control */ + hwndControls = GetDlgItem(hwndDlg, + IDC_CONTROLS); + ListView_SetExtendedListViewStyle(hwndControls, + LVS_EX_CHECKBOXES); + + GetClientRect(hwndControls, + &rcClient); + lvc.mask = LVCF_TEXT | LVCF_WIDTH; + lvc.pszText = TEXT(""); + lvc.cx = rcClient.right; + SendMessage(hwndControls, + LVM_INSERTCOLUMN, + 0, + (LPARAM)&lvc); + + /* update all controls */ + UpdatePrefDlgControls(Context, + (DWORD)-1); return TRUE; }
@@ -222,6 +518,17 @@ PostQuitMessage(0); break; } + + case IDC_ABOUT: + { + HICON hAppIcon = (HICON)GetClassLongPtrW(hwnd, + GCLP_HICON); + ShellAbout(hwnd, + lpAppTitle, + NULL, + hAppIcon); + break; + } } break; } @@ -350,7 +657,6 @@ static HWND CreateApplicationWindow(VOID) { - LPTSTR lpAppTitle; HWND hWnd;
PMIXER_WINDOW MixerWindow = HeapAlloc(hAppHeap, @@ -361,14 +667,6 @@ return NULL; }
- /* load the application title */ - if (AllocAndLoadString(&lpAppTitle, - hAppInstance, - IDS_SNDVOL32) == 0) - { - lpAppTitle = NULL; - } - if (mixerGetNumDevs() > 0) { hWnd = CreateWindowEx(WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT, @@ -401,11 +699,6 @@ LocalFree(lpErrMessage); }
- if (lpAppTitle != NULL) - { - LocalFree(lpAppTitle); - } - if (hWnd == NULL) { HeapFree(hAppHeap, @@ -426,6 +719,14 @@
hAppInstance = hInstance; hAppHeap = GetProcessHeap(); + + /* load the application title */ + if (AllocAndLoadString(&lpAppTitle, + hAppInstance, + IDS_SNDVOL32) == 0) + { + lpAppTitle = NULL; + }
InitCommonControls();
@@ -454,6 +755,11 @@ DestroyWindow(hMainWnd);
UnregisterApplicationClasses(); + + if (lpAppTitle != NULL) + { + LocalFree(lpAppTitle); + }
return 0; } _____
Modified: trunk/reactos/subsys/system/sndvol32/sndvol32.h --- trunk/reactos/subsys/system/sndvol32/sndvol32.h 2005-09-27 00:46:19 UTC (rev 18114) +++ trunk/reactos/subsys/system/sndvol32/sndvol32.h 2005-09-27 01:02:15 UTC (rev 18115) @@ -4,6 +4,7 @@
#include <windows.h> #include <mmsystem.h> #include <commctrl.h> +#include <shellapi.h> #include <stdio.h> #include <tchar.h> #include <string.h> @@ -63,6 +64,7 @@ } SND_MIXER, *PSND_MIXER;
typedef BOOL (CALLBACK *PFNSNDMIXENUMLINES)(PSND_MIXER Mixer, LPMIXERLINE Line, PVOID Context); +typedef BOOL (CALLBACK *PFNSNDMIXENUMCONNECTIONS)(PSND_MIXER Mixer, DWORD LineID, LPMIXERLINE Line, PVOID Context); typedef BOOL (CALLBACK *PFNSNDMIXENUMPRODUCTS)(PSND_MIXER Mixer, UINT Id, LPCTSTR ProductName, PVOID Context);
PSND_MIXER SndMixerCreate(HWND hWndNotification); @@ -73,7 +75,8 @@ INT SndMixerGetProductName(PSND_MIXER Mixer, LPTSTR lpBuffer, UINT uSize); BOOL SndMixerEnumProducts(PSND_MIXER Mixer, PFNSNDMIXENUMPRODUCTS EnumProc, PVOID Context); INT SndMixerGetDestinationCount(PSND_MIXER Mixer); -BOOL SndMixerEnumDestinationLines(PSND_MIXER Mixer, PFNSNDMIXENUMLINES EnumProc, PVOID Context); +BOOL SndMixerEnumLines(PSND_MIXER Mixer, PFNSNDMIXENUMLINES EnumProc, PVOID Context); +BOOL SndMixerEnumConnections(PSND_MIXER Mixer, DWORD LineID, PFNSNDMIXENUMCONNECTIONS EnumProc, PVOID Context);
/* * MISC _____
Modified: trunk/reactos/subsys/system/sndvol32/sndvol32.xml --- trunk/reactos/subsys/system/sndvol32/sndvol32.xml 2005-09-27 00:46:19 UTC (rev 18114) +++ trunk/reactos/subsys/system/sndvol32/sndvol32.xml 2005-09-27 01:02:15 UTC (rev 18115) @@ -4,7 +4,9 @@
<define name="__USE_W32API" /> <define name="UNICODE" /> <define name="_UNICODE" /> - <define name="_WIN32_WINNT">0x6501</define> + <define name="_WIN32_IE">0x0500</define> + <define name="_WIN32_WINNT">0x0600</define> + <define name="WINVER">0x0600</define> <library>ntdll</library> <library>user32</library> <library>gdi32</library>