Something went wrong. Try again.
Reactos
Something went wrong. Try again.
C++
at listview
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604// FontSub by Katayama Hirofumi MZ//// To the extent possible under law, the person who associated CC0 with// FontSub has waived all copyright and related or neighboring rights// to FontSub.//// You should have received a copy of the CC0 legalcode along with this// work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
#include <windows.h>#include <windowsx.h>#include <commctrl.h>#include <tchar.h>#include <vector> // for std::vector#include <set> // for std::set#include <string> // for std::basic_string#include <algorithm> // for std::sort#include <cstdio>#include <cstring>#include <cassert>#include "resource.h"
#define NAME_COLUMN_WIDTH 250#define SUB_COLUMN_WIDTH 250#define MAX_STRING 120
#ifndef _countof #define _countof(array) (sizeof(array) / sizeof(array[0]))#endif
typedef std::wstring STRING;
struct ITEM{ STRING m_Name, m_Substitute; BYTE m_CharSet1, m_CharSet2; ITEM(const STRING& Name, const STRING& Substitute, BYTE CharSet1, BYTE CharSet2) : m_Name(Name), m_Substitute(Substitute), m_CharSet1(CharSet1), m_CharSet2(CharSet2) { }};
/* global variables */HINSTANCE g_hInstance = NULL;HWND g_hMainWnd = NULL;HICON g_hIcon = NULL;HWND g_hListView = NULL;BOOL g_bModified = FALSE;BOOL g_bNeedsReboot = FALSE;INT g_iItem = 0;
LPCWSTR g_pszClassName = L"ReactOS Font Substitutes Editor";LPCWSTR g_pszFileHeader = L"Windows Registry Editor Version 5.00";
WCHAR g_szTitle[MAX_STRING];WCHAR g_szNameHead[MAX_STRING];WCHAR g_szSubstituteHead[MAX_STRING];
INT g_iSortColumn = 0;BOOL g_bSortAscendant = TRUE;
LPCWSTR g_pszKey = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes";
typedef std::set<STRING> FONTNAMESET;typedef std::vector<ITEM> ITEMVECTOR;
FONTNAMESET g_Names;ITEMVECTOR g_Items;STRING g_strFontName;STRING g_strSubstitute;BYTE g_CharSet1 = DEFAULT_CHARSET;BYTE g_CharSet2 = DEFAULT_CHARSET;
typedef struct CHARSET_ENTRY{ BYTE CharSet; LPCWSTR DisplayName;} CHARSET_ENTRY;
CHARSET_ENTRY g_CharSetList[] ={ { DEFAULT_CHARSET, L"DEFAULT_CHARSET (1)" }, { ANSI_CHARSET, L"ANSI_CHARSET (0)" }, { SYMBOL_CHARSET, L"SYMBOL_CHARSET (2)" }, { SHIFTJIS_CHARSET, L"SHIFTJIS_CHARSET (128)" }, { HANGUL_CHARSET, L"HANGUL_CHARSET (129)" }, { GB2312_CHARSET, L"GB2312_CHARSET (134)" }, { CHINESEBIG5_CHARSET, L"CHINESEBIG5_CHARSET (136)" }, { OEM_CHARSET, L"OEM_CHARSET (255)" }, { JOHAB_CHARSET, L"JOHAB_CHARSET (130)" }, { HEBREW_CHARSET, L"HEBREW_CHARSET (177)" }, { ARABIC_CHARSET, L"ARABIC_CHARSET (178)" }, { GREEK_CHARSET, L"GREEK_CHARSET (161)" }, { TURKISH_CHARSET, L"TURKISH_CHARSET (162)" }, { VIETNAMESE_CHARSET, L"VIETNAMESE_CHARSET (163)" }, { THAI_CHARSET, L"THAI_CHARSET (222)" }, { EASTEUROPE_CHARSET, L"EASTEUROPE_CHARSET (238)" }, { RUSSIAN_CHARSET, L"RUSSIAN_CHARSET (204)" }, { MAC_CHARSET, L"MAC_CHARSET (77)" }, { BALTIC_CHARSET, L"BALTIC_CHARSET (186)" }};const WCHAR g_LongestName[] = L"CHINESEBIG5_CHARSET (136)";
static void trim(STRING& str){ static const WCHAR Spaces[] = L" \t\r\n"; size_t i = str.find_first_not_of(Spaces); size_t j = str.find_last_not_of(Spaces); if (i == STRING::npos || j == STRING::npos) { str.clear(); } else { str = str.substr(i, j - i + 1); }}
static int CALLBACKEnumFontFamExProc(const ENUMLOGFONTW *pelf, const NEWTEXTMETRICW *pntm, int FontType, LPARAM lParam){ switch (pelf->elfFullName[0]) { case UNICODE_NULL: case L'@': break; default: g_Names.insert((const WCHAR *)pelf->elfFullName); } switch (pelf->elfLogFont.lfFaceName[0]) { case UNICODE_NULL: case L'@': break; default: g_Names.insert(pelf->elfLogFont.lfFaceName); } return 1;}
BOOL DoLoadNames(void){ g_Names.clear();
LOGFONTW lf; ZeroMemory(&lf, sizeof(lf)); lf.lfCharSet = DEFAULT_CHARSET;
HDC hDC = CreateCompatibleDC(NULL); EnumFontFamiliesExW(hDC, &lf, (FONTENUMPROCW)EnumFontFamExProc, 0, 0); DeleteDC(hDC);
return !g_Names.empty();}
inline bool ItemCompareByNameAscend(const ITEM& Item1, const ITEM& Item2){ return Item1.m_Name < Item2.m_Name;}
inline bool ItemCompareByNameDescend(const ITEM& Item1, const ITEM& Item2){ return Item1.m_Name > Item2.m_Name;}
inline bool ItemCompareBySubAscend(const ITEM& Item1, const ITEM& Item2){ return Item1.m_Substitute < Item2.m_Substitute;}
inline bool ItemCompareBySubDescend(const ITEM& Item1, const ITEM& Item2){ return Item1.m_Substitute > Item2.m_Substitute;}
void DoSort(INT iColumn, BOOL bAscendant = TRUE){ LV_COLUMN Column; ZeroMemory(&Column, sizeof(Column)); Column.mask = LVCF_IMAGE | LVCF_SUBITEM; Column.iImage = 2; Column.iSubItem = 0; ListView_SetColumn(g_hListView, 0, &Column); Column.iSubItem = 1; ListView_SetColumn(g_hListView, 1, &Column);
switch (iColumn) { case 0: Column.iSubItem = 0; if (bAscendant) { std::sort(g_Items.begin(), g_Items.end(), ItemCompareByNameAscend); Column.iImage = 0; ListView_SetColumn(g_hListView, 0, &Column); } else { std::sort(g_Items.begin(), g_Items.end(), ItemCompareByNameDescend); Column.iImage = 1; ListView_SetColumn(g_hListView, 0, &Column); } break; case 1: Column.iSubItem = 1; if (bAscendant) { std::sort(g_Items.begin(), g_Items.end(), ItemCompareBySubAscend); Column.iImage = 0; ListView_SetColumn(g_hListView, 1, &Column); } else { std::sort(g_Items.begin(), g_Items.end(), ItemCompareBySubDescend); Column.iImage = 1; ListView_SetColumn(g_hListView, 1, &Column); } break; } g_iSortColumn = iColumn; g_bSortAscendant = bAscendant; InvalidateRect(g_hListView, NULL, TRUE);}
void LV_AddItems(HWND hwnd){ ListView_DeleteAllItems(hwnd);
LV_ITEM Item; ZeroMemory(&Item, sizeof(Item)); Item.mask = LVIF_PARAM;
const INT Count = INT(g_Items.size()); for (INT i = 0; i < Count; ++i) { Item.iItem = i; Item.iSubItem = 0; Item.lParam = i; ListView_InsertItem(hwnd, &Item);
Item.iItem = i; Item.iSubItem = 1; Item.lParam = i; ListView_InsertItem(hwnd, &Item); }}
BOOL DoLoadItems(void){ ITEMVECTOR Items;
HKEY hKey = NULL; RegOpenKeyExW(HKEY_LOCAL_MACHINE, g_pszKey, 0, KEY_READ, &hKey); if (hKey == NULL) return FALSE;
WCHAR szName[MAX_STRING], szValue[MAX_STRING]; DWORD cbName, cbValue; for (DWORD dwIndex = 0; ; ++dwIndex) { cbName = sizeof(szName); cbValue = sizeof(szValue); LONG Error = RegEnumValueW(hKey, dwIndex, szName, &cbName, NULL, NULL, (LPBYTE)szValue, &cbValue); if (Error != ERROR_SUCCESS) break;
BYTE CharSet1 = DEFAULT_CHARSET, CharSet2 = DEFAULT_CHARSET; LPWSTR pch;
pch = wcsrchr(szName, L','); if (pch) { *pch = 0; CharSet1 = (BYTE)_wtoi(pch + 1); }
pch = wcsrchr(szValue, L','); if (pch) { *pch = 0; CharSet2 = (BYTE)_wtoi(pch + 1); }
ITEM Item(szName, szValue, CharSet1, CharSet2); trim(Item.m_Name); trim(Item.m_Substitute); Items.push_back(Item); }
RegCloseKey(hKey);
g_Items = Items; LV_AddItems(g_hListView); DoSort(0, TRUE); g_bModified = FALSE; g_bNeedsReboot = FALSE;
return !g_Items.empty();}
BOOL DoLoad(void){ return DoLoadNames() && DoLoadItems();}
void LV_InvalidateRow(HWND hwnd, INT iRow = -1){ if (iRow == -1) iRow = ListView_GetNextItem(hwnd, -1, LVNI_SELECTED); if (iRow == -1) return;
RECT Rect; LPRECT GccIsWhining = &Rect; ListView_GetItemRect(hwnd, iRow, GccIsWhining, LVIR_BOUNDS); InvalidateRect(hwnd, &Rect, FALSE);}
BOOL LV_Init(HWND hwnd){ ListView_SetExtendedListViewStyle(hwnd, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
HIMAGELIST hImageList; hImageList = ImageList_Create(12, 12, ILC_COLOR8 | ILC_MASK, 2, 2);
HBITMAP hbm; hbm = (HBITMAP)LoadImage(g_hInstance, MAKEINTRESOURCE(2), IMAGE_BITMAP, 12, 12, LR_CREATEDIBSECTION | LR_LOADMAP3DCOLORS); assert(hbm); ImageList_AddMasked(hImageList, hbm, RGB(192, 192, 192)); DeleteObject(hbm);
hbm = (HBITMAP)LoadImage(g_hInstance, MAKEINTRESOURCE(3), IMAGE_BITMAP, 12, 12, LR_CREATEDIBSECTION | LR_LOADMAP3DCOLORS); assert(hbm); ImageList_AddMasked(hImageList, hbm, RGB(192, 192, 192)); DeleteObject(hbm);
hbm = (HBITMAP)LoadImage(g_hInstance, MAKEINTRESOURCE(4), IMAGE_BITMAP, 12, 12, LR_CREATEDIBSECTION | LR_LOADMAP3DCOLORS); assert(hbm); ImageList_AddMasked(hImageList, hbm, RGB(192, 192, 192)); DeleteObject(hbm);
ListView_SetImageList(hwnd, hImageList, LVSIL_SMALL);
LV_COLUMNW Column; ZeroMemory(&Column, sizeof(Column)); Column.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH | LVCF_IMAGE; Column.fmt = LVCFMT_LEFT;
Column.cx = NAME_COLUMN_WIDTH; Column.pszText = g_szNameHead; Column.iSubItem = 0; Column.iImage = 0; ListView_InsertColumn(hwnd, 0, &Column);
Column.cx = SUB_COLUMN_WIDTH; Column.pszText = g_szSubstituteHead; Column.iSubItem = 1; Column.iImage = 2; ListView_InsertColumn(hwnd, 1, &Column);
UINT State = LVIS_SELECTED | LVIS_FOCUSED; ListView_SetItemState(hwnd, 0, State, State);
return TRUE;}
BOOL EditDlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam){ COMBOBOXEXITEMW Item; ZeroMemory(&Item, sizeof(Item)); Item.mask = CBEIF_TEXT;
FONTNAMESET::iterator it, end = g_Names.end(); for (it = g_Names.begin(); it != end; ++it) { Item.pszText = const_cast<LPWSTR>(it->c_str()); Item.iItem = ComboBox_GetCount(GetDlgItem(hwnd, cmb2)); SendDlgItemMessageW(hwnd, cmb2, CBEM_INSERTITEM, 0, (LPARAM)&Item); } SetDlgItemTextW(hwnd, edt1, g_strFontName.c_str()); SetDlgItemTextW(hwnd, cmb2, g_strSubstitute.c_str());
const INT Count = _countof(g_CharSetList); for (INT i = 0; i < Count; ++i) { Item.pszText = const_cast<LPWSTR>(g_CharSetList[i].DisplayName); Item.iItem = ComboBox_GetCount(GetDlgItem(hwnd, cmb3)); SendDlgItemMessageW(hwnd, cmb3, CBEM_INSERTITEM, 0, (LPARAM)&Item); Item.iItem = ComboBox_GetCount(GetDlgItem(hwnd, cmb4)); SendDlgItemMessageW(hwnd, cmb4, CBEM_INSERTITEM, 0, (LPARAM)&Item); }
SendDlgItemMessageW(hwnd, cmb3, CB_SETCURSEL, 0, 0); SendDlgItemMessageW(hwnd, cmb4, CB_SETCURSEL, 0, 0); for (INT i = 0; i < Count; ++i) { if (g_CharSet1 == g_CharSetList[i].CharSet) { SendDlgItemMessageW(hwnd, cmb3, CB_SETCURSEL, i, 0); } if (g_CharSet2 == g_CharSetList[i].CharSet) { SendDlgItemMessageW(hwnd, cmb4, CB_SETCURSEL, i, 0); } }
SIZE siz; HDC hDC = CreateCompatibleDC(NULL); SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT)); GetTextExtentPoint32W(hDC, g_LongestName, lstrlenW(g_LongestName), &siz); DeleteDC(hDC);
SendDlgItemMessageW(hwnd, cmb3, CB_SETHORIZONTALEXTENT, siz.cx + 16, 0); SendDlgItemMessageW(hwnd, cmb4, CB_SETHORIZONTALEXTENT, siz.cx + 16, 0);
EnableWindow(GetDlgItem(hwnd, cmb3), FALSE);
return TRUE;}
void LV_OnDelete(HWND hwnd, INT iRow = -1){ if (iRow == -1) iRow = ListView_GetNextItem(hwnd, -1, LVNI_SELECTED); if (iRow == -1) return;
UINT State = LVIS_SELECTED | LVIS_FOCUSED; ListView_SetItemState(g_hListView, iRow, State, State);
WCHAR sz[MAX_STRING]; LoadStringW(g_hInstance, IDS_QUERYDELETE, sz, _countof(sz)); if (IDYES != MessageBoxW(g_hMainWnd, sz, g_szTitle, MB_ICONINFORMATION | MB_YESNO)) { return; }
ListView_DeleteItem(hwnd, iRow); g_Items.erase(g_Items.begin() + iRow); g_bModified = TRUE;
ListView_SetItemState(g_hListView, iRow, State, State);
InvalidateRect(hwnd, NULL, TRUE);}
void EditDlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify){ WCHAR szValue[MAX_STRING]; STRING str; INT i;
switch (id) { case IDOK: GetDlgItemTextW(hwnd, cmb2, szValue, _countof(szValue)); str = szValue; trim(str); if (str.empty()) { WCHAR sz[MAX_STRING]; SendDlgItemMessageW(hwnd, cmb2, CB_SETEDITSEL, 0, MAKELPARAM(0, -1)); SetFocus(GetDlgItem(hwnd, cmb2)); LoadStringW(g_hInstance, IDS_ENTERNAME2, sz, _countof(sz)); MessageBoxW(hwnd, sz, NULL, MB_ICONERROR); return; }
g_Items[g_iItem].m_CharSet2 = DEFAULT_CHARSET; i = SendDlgItemMessageW(hwnd, cmb4, CB_GETCURSEL, 0, 0); if (i != CB_ERR) { g_Items[g_iItem].m_CharSet2 = g_CharSetList[i].CharSet; } g_Items[g_iItem].m_Substitute = str;
g_bModified = TRUE; EndDialog(hwnd, IDOK); break; case IDCANCEL: EndDialog(hwnd, IDCANCEL); break; case psh1: LV_OnDelete(g_hListView, g_iItem); EndDialog(hwnd, psh1); break; }}
INT_PTR CALLBACKEditDlg_DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ switch (uMsg) { HANDLE_MSG(hwnd, WM_INITDIALOG, EditDlg_OnInitDialog); HANDLE_MSG(hwnd, WM_COMMAND, EditDlg_OnCommand); } return 0;}
void LV_OnDblClk(HWND hwnd){ g_iItem = ListView_GetNextItem(hwnd, -1, LVNI_SELECTED); if (g_iItem == -1) return;
g_strFontName = g_Items[g_iItem].m_Name; g_strSubstitute = g_Items[g_iItem].m_Substitute; g_CharSet1 = g_Items[g_iItem].m_CharSet1; g_CharSet2 = g_Items[g_iItem].m_CharSet2;
DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_EDIT), g_hMainWnd, EditDlg_DlgProc); InvalidateRect(g_hListView, NULL, TRUE);}
BOOL MainWnd_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct){ DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_VSCROLL | LVS_SINGLESEL | LVS_REPORT | LVS_OWNERDRAWFIXED; DWORD dwExStyle = WS_EX_CLIENTEDGE; g_hListView = CreateWindowEx(dwExStyle, WC_LISTVIEW, NULL, dwStyle, 0, 0, 0, 0, hwnd, (HMENU)1, g_hInstance, NULL); if (g_hListView == NULL) return FALSE;
if (!LV_Init(g_hListView)) return FALSE;
if (!DoLoad()) return FALSE;
UINT State = LVIS_SELECTED | LVIS_FOCUSED; ListView_SetItemState(g_hListView, 0, State, State); SetFocus(g_hListView); return TRUE;}
BOOL AddDlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam){ COMBOBOXEXITEMW Item; ZeroMemory(&Item, sizeof(Item)); Item.iItem = -1; Item.mask = CBEIF_TEXT;
FONTNAMESET::iterator it, end = g_Names.end(); for (it = g_Names.begin(); it != end; ++it) { Item.pszText = const_cast<LPWSTR>(it->c_str()); Item.iItem = ComboBox_GetCount(GetDlgItem(hwnd, cmb1)); SendDlgItemMessageW(hwnd, cmb1, CBEM_INSERTITEM, 0, (LPARAM)&Item); Item.iItem = ComboBox_GetCount(GetDlgItem(hwnd, cmb2)); SendDlgItemMessageW(hwnd, cmb2, CBEM_INSERTITEM, 0, (LPARAM)&Item); } WCHAR szEnterName[MAX_STRING]; LoadStringW(g_hInstance, IDS_ENTERNAME, szEnterName, _countof(szEnterName)); SetDlgItemTextW(hwnd, cmb1, szEnterName); SendDlgItemMessageW(hwnd, cmb1, CB_SETEDITSEL, 0, MAKELPARAM(0, -1));
const INT Count = _countof(g_CharSetList); for (INT i = 0; i < Count; ++i) { Item.pszText = const_cast<LPWSTR>(g_CharSetList[i].DisplayName); Item.iItem = ComboBox_GetCount(GetDlgItem(hwnd, cmb3)); SendDlgItemMessageW(hwnd, cmb3, CBEM_INSERTITEM, 0, (LPARAM)&Item); Item.iItem = ComboBox_GetCount(GetDlgItem(hwnd, cmb4)); SendDlgItemMessageW(hwnd, cmb4, CBEM_INSERTITEM, 0, (LPARAM)&Item); }
SendDlgItemMessageW(hwnd, cmb3, CB_SETCURSEL, 0, 0); SendDlgItemMessageW(hwnd, cmb4, CB_SETCURSEL, 0, 0); for (INT i = 0; i < Count; ++i) { if (g_CharSet1 == g_CharSetList[i].CharSet) { SendDlgItemMessageW(hwnd, cmb3, CB_SETCURSEL, i, 0); } if (g_CharSet2 == g_CharSetList[i].CharSet) { SendDlgItemMessageW(hwnd, cmb4, CB_SETCURSEL, i, 0); } }
SIZE siz; HDC hDC = CreateCompatibleDC(NULL); SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT)); GetTextExtentPoint32W(hDC, g_LongestName, lstrlenW(g_LongestName), &siz); DeleteDC(hDC);
SendDlgItemMessageW(hwnd, cmb3, CB_SETHORIZONTALEXTENT, siz.cx + 16, 0); SendDlgItemMessageW(hwnd, cmb4, CB_SETHORIZONTALEXTENT, siz.cx + 16, 0);
return TRUE;}
void AddDlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify){ WCHAR szKey[MAX_STRING], szValue[MAX_STRING], sz[MAX_STRING]; INT i, iCharSet1, iCharSet2; BYTE CharSet1, CharSet2; STRING key, value; switch (id) { case IDOK: GetDlgItemTextW(hwnd, cmb1, szKey, _countof(szKey)); key = szKey; trim(key); LoadStringW(g_hInstance, IDS_ENTERNAME, sz, _countof(sz)); if (key.empty() || key == sz) { SendDlgItemMessageW(hwnd, cmb1, CB_SETEDITSEL, 0, MAKELPARAM(0, -1)); SetFocus(GetDlgItem(hwnd, cmb1)); LoadStringW(g_hInstance, IDS_ENTERNAME2, sz, _countof(sz)); MessageBoxW(hwnd, sz, NULL, MB_ICONERROR); return; }
GetDlgItemTextW(hwnd, cmb2, szValue, _countof(szValue)); value = szValue; trim(value); if (value.empty()) { SendDlgItemMessageW(hwnd, cmb2, CB_SETEDITSEL, 0, MAKELPARAM(0, -1)); SetFocus(GetDlgItem(hwnd, cmb2)); LoadStringW(g_hInstance, IDS_ENTERNAME2, sz, _countof(sz)); MessageBoxW(hwnd, sz, NULL, MB_ICONERROR); return; }
iCharSet1 = SendDlgItemMessageW(hwnd, cmb3, CB_GETCURSEL, 0, 0); if (iCharSet1 == CB_ERR) iCharSet1 = 0; iCharSet2 = SendDlgItemMessageW(hwnd, cmb4, CB_GETCURSEL, 0, 0); if (iCharSet2 == CB_ERR) iCharSet2 = 0;
CharSet1 = g_CharSetList[iCharSet1].CharSet; CharSet2 = g_CharSetList[iCharSet2].CharSet;
for (i = 0; i < (INT)g_Items.size(); ++i) { if (g_Items[i].m_Name == key && g_Items[i].m_CharSet1 == CharSet1) { WCHAR sz[MAX_STRING]; SendDlgItemMessageW(hwnd, cmb1, CB_SETEDITSEL, 0, MAKELPARAM(0, -1)); SetFocus(GetDlgItem(hwnd, cmb1)); LoadStringW(g_hInstance, IDS_ALREADYEXISTS, sz, _countof(sz)); MessageBoxW(hwnd, sz, NULL, MB_ICONERROR); return; } } { ITEM Item(key, value, CharSet1, CharSet2); g_Items.push_back(Item); g_bModified = TRUE;
i = (INT)g_Items.size(); LV_ITEM LvItem; ZeroMemory(&LvItem, sizeof(LvItem)); LvItem.mask = LVIF_PARAM; LvItem.iItem = i; LvItem.lParam = i;
LvItem.iSubItem = 0; ListView_InsertItem(g_hListView, &LvItem);
LvItem.iSubItem = 1; ListView_InsertItem(g_hListView, &LvItem); } g_bModified = TRUE; EndDialog(hwnd, IDOK); break; case IDCANCEL: EndDialog(hwnd, IDCANCEL); break; }}
INT_PTR CALLBACKAddDlg_DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ switch (uMsg) { HANDLE_MSG(hwnd, WM_INITDIALOG, AddDlg_OnInitDialog); HANDLE_MSG(hwnd, WM_COMMAND, AddDlg_OnCommand); } return 0;}
void MainWnd_OnNew(HWND hwnd){ g_iItem = ListView_GetNextItem(hwnd, -1, LVNI_SELECTED); if (g_iItem == -1) return;
g_strFontName = g_Items[g_iItem].m_Name; g_strSubstitute = g_Items[g_iItem].m_Substitute; g_CharSet1 = g_Items[g_iItem].m_CharSet1; g_CharSet2 = g_Items[g_iItem].m_CharSet2;
if (IDOK == DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_ADD), g_hMainWnd, AddDlg_DlgProc)) { INT i = ListView_GetItemCount(g_hListView) - 1; UINT State = LVIS_SELECTED | LVIS_FOCUSED; ListView_SetItemState(g_hListView, i, State, State); ListView_EnsureVisible(g_hListView, i, FALSE); }}
BOOL MainWnd_OnUpdateRegistry(HWND hwnd){ // open the key HKEY hKey = NULL; RegOpenKeyExW(HKEY_LOCAL_MACHINE, g_pszKey, 0, KEY_ALL_ACCESS, &hKey); if (hKey == NULL) return FALSE;
// clear all values WCHAR szName[MAX_STRING], szValue[MAX_STRING]; DWORD cbName, cbValue; for (;;) { cbName = sizeof(szName); cbValue = sizeof(szValue); LONG Error = RegEnumValueW(hKey, 0, szName, &cbName, NULL, NULL, (LPBYTE)szValue, &cbValue); if (Error != ERROR_SUCCESS) break;
RegDeleteValueW(hKey, szName); }
// set values size_t Count = g_Items.size(); for (size_t i = 0; i < Count; ++i) { DWORD cbData = (g_Items[i].m_Substitute.size() + 1) * sizeof(WCHAR); RegSetValueExW(hKey, g_Items[i].m_Name.c_str(), 0, REG_SZ, (LPBYTE)g_Items[i].m_Substitute.c_str(), cbData); }
// close now RegCloseKey(hKey);
g_bModified = FALSE; g_bNeedsReboot = TRUE; return TRUE;}
LPWSTR SkipSpace(LPCWSTR pch){ while (*pch && wcschr(L" \t\r\n", *pch) != NULL) { ++pch; } return const_cast<LPWSTR>(pch);}
LPWSTR SkipQuoted(LPWSTR pch){ ++pch; // L'"' while (*pch) { if (*pch == L'"') { ++pch; break; } if (*pch == L'\\') { ++pch; } ++pch; } return pch;}
void UnescapeHex(const STRING& str, size_t& i, STRING& Ret, BOOL Unicode){ STRING Num;
// hexadecimal if (iswxdigit(str[i])) { Num += str[i]; ++i; if (iswxdigit(str[i])) { Num += str[i]; ++i; if (Unicode) { if (iswxdigit(str[i])) { Num += str[i]; ++i; if (iswxdigit(str[i])) { Num += str[i]; ++i; } } } } } if (!Num.empty()) { Ret += (WCHAR)wcstoul(&Num[0], NULL, 16); }}
void UnescapeOther(const STRING& str, size_t& i, STRING& Ret){ STRING Num;
// check octal if (L'0' <= str[i] && str[i] < L'8') { Num += str[i]; ++i; if (L'0' <= str[i] && str[i] < L'8') { Num += str[i]; ++i; if (L'0' <= str[i] && str[i] < L'8') { Num += str[i]; ++i; } } } if (Num.empty()) { Ret += str[i]; ++i; } else { // octal Ret += (WCHAR)wcstoul(&Num[0], NULL, 8); }}
// process escape sequencevoid UnescapeChar(const STRING& str, size_t& i, STRING& Ret){ if (str[i] != L'\\') { Ret += str[i]; ++i; return; }
++i; switch (str[i]) { case L'a': Ret += L'\a'; ++i; break; case L'b': Ret += L'\b'; ++i; break; case L'f': Ret += L'\f'; ++i; break; case L'n': Ret += L'\n'; ++i; break; case L'r': Ret += L'\r'; ++i; break; case L't': Ret += L'\t'; ++i; break; case L'v': Ret += L'\v'; ++i; break; case L'x': // hexidemical ++i; UnescapeHex(str, i, Ret, FALSE); break; case L'u': // Unicode hexidemical ++i; UnescapeHex(str, i, Ret, TRUE); break; default: // other case UnescapeOther(str, i, Ret); break; }}
STRING Unquote(const STRING& str){ if (str[0] != L'"') return str;
STRING Ret; size_t i = 1; while (i < str.size()) { if (str[i] == L'"' || str[i] == UNICODE_NULL) break;
UnescapeChar(str, i, Ret); } return Ret;}
BOOL DoParseFile(LPVOID pvContents, DWORD dwSize){ ITEMVECTOR Items;
LPWSTR pch, pchSep, pchStart = (LPWSTR)pvContents;
pchStart[dwSize / sizeof(WCHAR)] = UNICODE_NULL;
// check header const DWORD cbHeader = lstrlenW(g_pszFileHeader) * sizeof(WCHAR); if (memcmp(pchStart, g_pszFileHeader, cbHeader) != 0) return FALSE;
pchStart += cbHeader / sizeof(WCHAR);
// find the key WCHAR szKey[MAX_STRING]; wsprintfW(szKey, L"[HKEY_LOCAL_MACHINE\\%s]", g_pszKey); pch = wcsstr(pchStart, szKey); if (pch == NULL) return FALSE;
pchStart = pch + lstrlenW(szKey);
for (;;) { pchStart = SkipSpace(pchStart); if (*pchStart == UNICODE_NULL || *pchStart == L'[') break;
pch = wcschr(pchStart, L'\n'); if (pch) *pch = UNICODE_NULL;
pchSep = SkipQuoted(pchStart); if (*pchSep == L'=') { *pchSep = UNICODE_NULL;
STRING key = pchStart; trim(key); key = Unquote(key);
STRING value = pchSep + 1; trim(value); value = Unquote(value);
BYTE CharSet1 = DEFAULT_CHARSET, CharSet2 = DEFAULT_CHARSET;
size_t pos; pos = key.find(L','); if (pos != STRING::npos) { CharSet1 = (BYTE)_wtoi(&key[pos + 1]); key.resize(pos); trim(key); } pos = value.find(L','); if (pos != STRING::npos) { CharSet2 = (BYTE)_wtoi(&value[pos + 1]); value.resize(pos); trim(value); }
ITEM Item(key, value, CharSet1, CharSet2); Items.push_back(Item); }
if (pch == NULL) break;
pchStart = pch + 1; }
g_Items = Items; g_bModified = TRUE;
LV_AddItems(g_hListView); return TRUE;}
BOOL DoImport(HWND hwnd, LPCWSTR pszFile){ HANDLE hFile = CreateFileW(pszFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE;
BOOL bSuccess = FALSE; DWORD dwSize = GetFileSize(hFile, NULL); if (dwSize != 0xFFFFFFFF) { std::vector<BYTE> Contents(dwSize + 2); DWORD cbRead; if (ReadFile(hFile, &Contents[0], dwSize, &cbRead, NULL) && cbRead == dwSize) { /* check BOM */ if (memcmp(&Contents[0], "\xFF\xFE", 2) == 0) { bSuccess = DoParseFile(&Contents[2], dwSize - 2); } else { bSuccess = DoParseFile(&Contents[0], dwSize); } } } CloseHandle(hFile);
return bSuccess;}
STRING Escape(const STRING& str){ STRING Ret; for (size_t i = 0; i < str.size(); ++i) { switch (str[i]) { case L'"': case L'\\': Ret += L'\\'; Ret += str[i]; break; default: Ret += str[i]; } } return Ret;}
BOOL DoExport(HWND hwnd, LPCWSTR pszFile){ HANDLE hFile = CreateFileW(pszFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE;
BOOL bSuccess; DWORD dwSize, cbWritten; WCHAR szCharSet1[MAX_STRING], szCharSet2[MAX_STRING]; WCHAR szLine[MAX_STRING * 2 + 4];
/* write header */ dwSize = lstrlenW(g_pszFileHeader) * sizeof(WCHAR); bSuccess = WriteFile(hFile, "\xFF\xFE", 2, &cbWritten, NULL) && WriteFile(hFile, g_pszFileHeader, dwSize, &cbWritten, NULL); if (bSuccess) { wsprintfW(szLine, L"\r\n\r\n[HKEY_LOCAL_MACHINE\\%s]\r\n", g_pszKey); dwSize = lstrlenW(szLine) * sizeof(WCHAR); bSuccess = WriteFile(hFile, szLine, dwSize, &cbWritten, NULL); } if (bSuccess) { size_t i, Count = g_Items.size(); for (i = 0; i < Count; ++i) { if (g_Items[i].m_CharSet1 != DEFAULT_CHARSET) wsprintfW(szCharSet1, L",%u", g_Items[i].m_CharSet1); else szCharSet1[0] = UNICODE_NULL;
if (g_Items[i].m_CharSet2 != DEFAULT_CHARSET) wsprintfW(szCharSet2, L",%u", g_Items[i].m_CharSet2); else szCharSet2[0] = UNICODE_NULL;
STRING Name = Escape(g_Items[i].m_Name); STRING Substitute = Escape(g_Items[i].m_Substitute); wsprintfW(szLine, L"\"%s%s\"=\"%s%s\"\r\n", Name.c_str(), szCharSet1, Substitute.c_str(), szCharSet2);
dwSize = lstrlenW(szLine) * sizeof(WCHAR); if (!WriteFile(hFile, szLine, dwSize, &cbWritten, NULL)) { bSuccess = FALSE; break; } } WriteFile(hFile, L"\r\n", 2 * sizeof(WCHAR), &cbWritten, NULL); } CloseHandle(hFile);
if (!bSuccess) { DeleteFileW(pszFile); }
return bSuccess;}
void MakeFilter(LPWSTR pszFilter){ while (*pszFilter) { if (*pszFilter == L'|') *pszFilter = 0;
++pszFilter; }}
void MainWnd_OnImport(HWND hwnd){ OPENFILENAMEW ofn = {0}; WCHAR szFile[MAX_PATH] = L""; WCHAR szImportTitle[MAX_STRING]; WCHAR szCannotImport[MAX_STRING]; WCHAR szImportFilter[MAX_STRING]; LoadStringW(g_hInstance, IDS_IMPORT, szImportTitle, _countof(szImportTitle)); LoadStringW(g_hInstance, IDS_CANTIMPORT, szCannotImport, _countof(szCannotImport)); LoadStringW(g_hInstance, IDS_INPFILTER, szImportFilter, _countof(szImportFilter)); MakeFilter(szImportFilter);
ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; ofn.hwndOwner = hwnd; ofn.lpstrFilter = szImportFilter; ofn.lpstrFile = szFile; ofn.nMaxFile = _countof(szFile); ofn.lpstrTitle = szImportTitle; ofn.Flags = OFN_DONTADDTORECENT | OFN_ENABLESIZING | OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_LONGNAMES | OFN_PATHMUSTEXIST; ofn.lpstrDefExt = L"reg"; if (GetOpenFileNameW(&ofn)) { if (!DoImport(hwnd, szFile)) { MessageBoxW(hwnd, szCannotImport, g_szTitle, MB_ICONERROR); } }}
void MainWnd_OnExport(HWND hwnd){ OPENFILENAMEW ofn = {0}; WCHAR szFile[MAX_PATH] = L""; WCHAR szExportTitle[MAX_STRING]; WCHAR szCannotExport[MAX_STRING]; WCHAR szExportFilter[MAX_STRING]; LoadStringW(g_hInstance, IDS_EXPORT, szExportTitle, _countof(szExportTitle)); LoadStringW(g_hInstance, IDS_CANTEXPORT, szCannotExport, _countof(szCannotExport)); LoadStringW(g_hInstance, IDS_OUTFILTER, szExportFilter, _countof(szExportFilter)); MakeFilter(szExportFilter);
ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; ofn.hwndOwner = hwnd; ofn.lpstrFilter = szExportFilter; ofn.lpstrFile = szFile; ofn.nMaxFile = _countof(szFile); ofn.lpstrTitle = szExportTitle; ofn.Flags = OFN_DONTADDTORECENT | OFN_ENABLESIZING | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_LONGNAMES | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT; ofn.lpstrDefExt = L"reg"; if (GetSaveFileNameW(&ofn)) { if (!DoExport(hwnd, szFile)) { MessageBoxW(hwnd, szCannotExport, g_szTitle, MB_ICONERROR); } }}
void MainWnd_OnReload(HWND hwnd){ DoLoad();}
void MainWnd_OnEdit(HWND hwnd){ LV_OnDblClk(g_hListView);}
void MainWnd_OnDelete(HWND hwnd){ LV_OnDelete(g_hListView);}
void MainWnd_OnOpenRegKey(HWND hwnd){ static const WCHAR s_szRegeditKey[] = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit"; WCHAR sz[MAX_STRING];
// open regedit key HKEY hKey = NULL; LSTATUS Result = RegCreateKeyExW(HKEY_CURRENT_USER, s_szRegeditKey, 0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL); if (Result != ERROR_SUCCESS) { LoadStringW(g_hInstance, IDS_CANTOPENKEY, sz, _countof(sz)); MessageBoxW(hwnd, sz, NULL, MB_ICONERROR); return; }
// set LastKey value wsprintfW(sz, L"HKEY_LOCAL_MACHINE\\%s", g_pszKey); DWORD dwSize = sizeof(sz); Result = RegSetValueExW(hKey, L"LastKey", 0, REG_SZ, (LPBYTE)sz, dwSize);
// close now RegCloseKey(hKey);
if (Result != ERROR_SUCCESS) { LoadStringW(g_hInstance, IDS_CANTOPENKEY, sz, _countof(sz)); MessageBoxW(hwnd, sz, NULL, MB_ICONERROR); return; }
// open by regedit ShellExecuteW(hwnd, NULL, L"regedit.exe", NULL, NULL, SW_SHOWNORMAL);}
void MainWnd_OnAbout(HWND hwnd){ WCHAR szAbout[MAX_PATH]; LoadStringW(g_hInstance, IDS_ABOUT, szAbout, _countof(szAbout));
MSGBOXPARAMS Params; ZeroMemory(&Params, sizeof(Params)); Params.cbSize = sizeof(Params); Params.hwndOwner = hwnd; Params.hInstance = g_hInstance; Params.lpszText = szAbout; Params.lpszCaption = g_szTitle; Params.dwStyle = MB_OK | MB_USERICON; Params.lpszIcon = MAKEINTRESOURCEW(1); Params.dwLanguageId = LANG_USER_DEFAULT; MessageBoxIndirectW(&Params);}
void MainWnd_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify){ switch (id) { case ID_NEW: MainWnd_OnNew(hwnd); break; case ID_EDIT: MainWnd_OnEdit(hwnd); break; case ID_EXIT: PostMessage(hwnd, WM_CLOSE, 0, 0); break; case ID_RELOAD: MainWnd_OnReload(hwnd); break; case ID_UPDATE_REGISTRY: MainWnd_OnUpdateRegistry(hwnd); break; case ID_DELETE: MainWnd_OnDelete(hwnd); break; case ID_IMPORT: MainWnd_OnImport(hwnd); break; case ID_EXPORT: MainWnd_OnExport(hwnd); break; case ID_OPEN_REGKEY: MainWnd_OnOpenRegKey(hwnd); break; case ID_ABOUT: MainWnd_OnAbout(hwnd); break; }}
void MainWnd_OnDestroy(HWND hwnd){ PostQuitMessage(0);}
void MainWnd_OnSize(HWND hwnd, UINT state, int cx, int cy){ MoveWindow(g_hListView, 0, 0, cx, cy, TRUE);}
void MainWnd_OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT *lpDrawItem){ if (lpDrawItem->CtlType != ODT_LISTVIEW) return;
HDC hDC = lpDrawItem->hDC; SetBkMode(hDC, TRANSPARENT);
INT iColumn = 0, x, cx; RECT rcItem, rcSubItem, rcText; STRING Str;
x = -GetScrollPos(g_hListView, SB_HORZ);
rcItem = lpDrawItem->rcItem; if (lpDrawItem->itemState & ODS_SELECTED) { FillRect(hDC, &rcItem, (HBRUSH)(COLOR_HIGHLIGHT + 1)); SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); } else { FillRect(hDC, &rcItem, (HBRUSH)(COLOR_WINDOW + 1)); SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); }
cx = ListView_GetColumnWidth(g_hListView, iColumn); rcSubItem = rcItem; rcSubItem.left = x; rcSubItem.right = x + cx;
WCHAR sz[MAX_STRING];
rcText = rcSubItem; InflateRect(&rcText, -1, -1); Str = g_Items[lpDrawItem->itemID].m_Name; BYTE CharSet1 = g_Items[lpDrawItem->itemID].m_CharSet1; if (CharSet1 != DEFAULT_CHARSET) wsprintfW(sz, L"%s,%u", Str.c_str(), CharSet1); else wsprintfW(sz, L"%s", Str.c_str());
DrawTextW(hDC, sz, lstrlenW(sz), &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);
x += cx; ++iColumn;
cx = ListView_GetColumnWidth(g_hListView, iColumn); rcSubItem = rcItem; rcSubItem.left = x; rcSubItem.right = x + cx;
rcText = rcSubItem; InflateRect(&rcText, -1, -1); Str = g_Items[lpDrawItem->itemID].m_Substitute; BYTE CharSet2 = g_Items[lpDrawItem->itemID].m_CharSet2; if (CharSet2 != DEFAULT_CHARSET) wsprintfW(sz, L"%s,%u", Str.c_str(), CharSet2); else wsprintfW(sz, L"%s", Str.c_str());
DrawTextW(hDC, sz, lstrlenW(sz), &rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER | DT_END_ELLIPSIS | DT_NOPREFIX);}
void MainWnd_OnMeasureItem(HWND hwnd, MEASUREITEMSTRUCT *lpMeasureItem){ if (lpMeasureItem->CtlType != ODT_LISTVIEW) return;
TEXTMETRIC tm; HDC hDC = GetDC(hwnd); GetTextMetrics(hDC, &tm); ReleaseDC(hwnd, hDC);
lpMeasureItem->itemHeight = tm.tmHeight * 4 / 3;}
LRESULT MainWnd_OnNotify(HWND hwnd, int idFrom, NMHDR *pnmhdr){ NM_LISTVIEW *pNMLV = (NM_LISTVIEW *)pnmhdr; LV_KEYDOWN *pLVKD = (LV_KEYDOWN *)pnmhdr;
switch (pnmhdr->code) { case LVN_COLUMNCLICK: if (pNMLV->iSubItem == g_iSortColumn) DoSort(pNMLV->iSubItem, !g_bSortAscendant); else DoSort(pNMLV->iSubItem, TRUE); break; case NM_DBLCLK: LV_OnDblClk(g_hListView); break; case LVN_KEYDOWN: if (pLVKD->wVKey == VK_RETURN) // [Enter] key { LV_OnDblClk(g_hListView); } if (pLVKD->wVKey == VK_DELETE) // [Del] key { LV_OnDelete(g_hListView); } break; } return 0;}
LRESULT MainWnd_OnContextMenu(HWND hwnd, HWND hwndContext, UINT xPos, UINT yPos){ POINT pt = {(INT)xPos, (INT)yPos}; ScreenToClient(g_hListView, &pt); SendMessageW(g_hListView, WM_LBUTTONDOWN, 0, MAKELPARAM(pt.x, pt.y));
HMENU hMenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(2)); if (hMenu == NULL) return 0;
HMENU hSubMenu = GetSubMenu(hMenu, 0); if (hSubMenu == NULL) return 0;
SetForegroundWindow(hwnd); TrackPopupMenu(hSubMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, xPos, yPos, 0, g_hMainWnd, NULL); PostMessage(g_hMainWnd, WM_NULL, 0, 0); return 0;}
void MainWnd_OnActivate(HWND hwnd, UINT state, HWND hwndActDeact, BOOL fMinimized){ if (state != WA_INACTIVE) { SetFocus(g_hListView); }}
BOOL EnableProcessPrivileges(LPCWSTR lpPrivilegeName, BOOL bEnable = TRUE){ HANDLE hToken; LUID luid; TOKEN_PRIVILEGES tokenPrivileges; BOOL Ret;
Ret = ::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken); if (!Ret) return Ret; // failure
Ret = ::LookupPrivilegeValueW(NULL, lpPrivilegeName, &luid); if (Ret) { tokenPrivileges.PrivilegeCount = 1; tokenPrivileges.Privileges[0].Luid = luid; tokenPrivileges.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
Ret = ::AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, 0, 0); }
::CloseHandle(hToken); return Ret;}
void MainWnd_OnClose(HWND hwnd){ if (!g_bNeedsReboot && !g_bModified) { DestroyWindow(hwnd); return; }
if (g_bModified) { WCHAR szUpdateNow[MAX_STRING]; LoadStringW(g_hInstance, IDS_QUERYUPDATE, szUpdateNow, _countof(szUpdateNow)); INT id = MessageBoxW(hwnd, szUpdateNow, g_szTitle, MB_ICONINFORMATION | MB_YESNOCANCEL); switch (id) { case IDYES: MainWnd_OnUpdateRegistry(hwnd); break; case IDNO: break; case IDCANCEL: return; } }
if (g_bNeedsReboot) { WCHAR szRebootNow[MAX_STRING]; LoadStringW(g_hInstance, IDS_REBOOTNOW, szRebootNow, _countof(szRebootNow)); INT id = MessageBoxW(hwnd, szRebootNow, g_szTitle, MB_ICONINFORMATION | MB_YESNOCANCEL); switch (id) { case IDYES: EnableProcessPrivileges(SE_SHUTDOWN_NAME, TRUE); ::ExitWindowsEx(EWX_REBOOT | EWX_FORCE, 0); break; case IDNO: break; case IDCANCEL: return; } }
::DestroyWindow(hwnd);}
LRESULT CALLBACKWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ switch (uMsg) { HANDLE_MSG(hwnd, WM_CREATE, MainWnd_OnCreate); HANDLE_MSG(hwnd, WM_COMMAND, MainWnd_OnCommand); HANDLE_MSG(hwnd, WM_DESTROY, MainWnd_OnDestroy); HANDLE_MSG(hwnd, WM_SIZE, MainWnd_OnSize); HANDLE_MSG(hwnd, WM_DRAWITEM, MainWnd_OnDrawItem); HANDLE_MSG(hwnd, WM_MEASUREITEM, MainWnd_OnMeasureItem); HANDLE_MSG(hwnd, WM_NOTIFY, MainWnd_OnNotify); HANDLE_MSG(hwnd, WM_CONTEXTMENU, MainWnd_OnContextMenu); HANDLE_MSG(hwnd, WM_ACTIVATE, MainWnd_OnActivate); HANDLE_MSG(hwnd, WM_CLOSE, MainWnd_OnClose); default: return DefWindowProc(hwnd, uMsg, wParam, lParam); }}
INT WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, INT nCmdShow){ g_hInstance = hInstance; InitCommonControls();
HACCEL hAccel = LoadAcceleratorsW(hInstance, MAKEINTRESOURCEW(1));
LoadStringW(hInstance, IDS_TITLE, g_szTitle, _countof(g_szTitle)); LoadStringW(hInstance, IDS_FONTNAME, g_szNameHead, _countof(g_szNameHead)); LoadStringW(hInstance, IDS_SUBSTITUTE, g_szSubstituteHead, _countof(g_szSubstituteHead));
WNDCLASSW wc = {0}; wc.style = 0; wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; g_hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(1)); wc.hIcon = g_hIcon; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); wc.lpszMenuName = MAKEINTRESOURCEW(1); wc.lpszClassName = g_pszClassName; if (!RegisterClassW(&wc)) { MessageBoxA(NULL, "ERROR: RegisterClass failed.", NULL, MB_ICONERROR); return 1; }
const DWORD dwStyle = WS_OVERLAPPEDWINDOW; INT Width = NAME_COLUMN_WIDTH + SUB_COLUMN_WIDTH + GetSystemMetrics(SM_CXVSCROLL) + GetSystemMetrics(SM_CXSIZEFRAME); INT Height = 320;
RECT Rect = { 0, 0, Width, Height }; AdjustWindowRect(&Rect, dwStyle, TRUE); Width = Rect.right - Rect.left; Height = Rect.bottom - Rect.top;
g_hMainWnd = CreateWindowW(g_pszClassName, g_szTitle, dwStyle, CW_USEDEFAULT, CW_USEDEFAULT, Width, Height, NULL, NULL, hInstance, NULL); if (g_hMainWnd == NULL) { MessageBoxA(NULL, "ERROR: CreateWindow failed.", NULL, MB_ICONERROR); return 2; }
ShowWindow(g_hMainWnd, nCmdShow); UpdateWindow(g_hMainWnd);
MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { if (TranslateAccelerator(g_hMainWnd, hAccel, &msg)) continue;
TranslateMessage(&msg); DispatchMessage(&msg); }
return (INT)msg.wParam;}