void SetUserFriendlyFont(HWND hConWnd) { OSVERSIONINFO OSVer = {sizeof(OSVer)}; GetVersionEx(&OSVer); // Соответствующие функции появились только в API Vista // Win2k & WinXP - доступны только хаки, что не подходит if (OSVer.dwMajorVersion >= 6) { HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); COORD crVisibleSize = {}; CONSOLE_SCREEN_BUFFER_INFO csbi = {}; if (GetConsoleScreenBufferInfo(hOutput, &csbi)) { crVisibleSize.X = csbi.srWindow.Right - csbi.srWindow.Left + 1; crVisibleSize.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; } if ((crVisibleSize.X <= 0) && (crVisibleSize.Y <= 0)) { _ASSERTE((crVisibleSize.X > 0) && (crVisibleSize.Y > 0)); } else { int curSizeY, curSizeX; wchar_t sFontName[LF_FACESIZE]; if (apiGetConsoleFontSize(hOutput, curSizeY, curSizeX, sFontName) && curSizeY && curSizeX) { DEBUGTEST(COORD crLargest = MyGetLargestConsoleWindowSize(hOutput)); HMONITOR hMon = MonitorFromWindow(hConWnd, MONITOR_DEFAULTTOPRIMARY); MONITORINFO mi = {sizeof(mi)}; int nMaxX = 0, nMaxY = 0; if (GetMonitorInfo(hMon, &mi)) { nMaxX = mi.rcWork.right - mi.rcWork.left - 2*GetSystemMetrics(SM_CXSIZEFRAME) - GetSystemMetrics(SM_CYCAPTION); nMaxY = mi.rcWork.bottom - mi.rcWork.top - 2*GetSystemMetrics(SM_CYSIZEFRAME); } if ((nMaxX > 0) && (nMaxY > 0)) { int nFontX = nMaxX / crVisibleSize.X; int nFontY = nMaxY / crVisibleSize.Y; // Too large height? if (nFontY > 28) { nFontX = 28 * nFontX / nFontY; nFontY = 28; } // Evaluate default width for the font int nEvalX = EvaluateDefaultFontWidth(nFontY, sFontName); if (nEvalX > 0) { if ((nEvalX > nFontX) && (nFontX > 0)) nFontY = nFontX * nFontY / nEvalX; else nFontX = nEvalX; } // Look in the registry? HKEY hk; DWORD nRegSize = 0, nLen; if (!RegOpenKeyEx(HKEY_CURRENT_USER, L"Console", 0, KEY_READ, &hk)) { if (RegQueryValueEx(hk, L"FontSize", NULL, NULL, (LPBYTE)&nRegSize, &(nLen=sizeof(nRegSize))) || nLen!=sizeof(nRegSize)) nRegSize = 0; RegCloseKey(hk); } if (!nRegSize && !RegOpenKeyEx(HKEY_CURRENT_USER, L"Console\\%SystemRoot%_system32_cmd.exe", 0, KEY_READ, &hk)) { if (RegQueryValueEx(hk, L"FontSize", NULL, NULL, (LPBYTE)&nRegSize, &(nLen=sizeof(nRegSize))) || nLen!=sizeof(nRegSize)) nRegSize = 0; RegCloseKey(hk); } if ((HIWORD(nRegSize) > curSizeY) && (HIWORD(nRegSize) < nFontY) && (LOWORD(nRegSize) > curSizeX) && (LOWORD(nRegSize) < nFontX)) { nFontY = HIWORD(nRegSize); nFontX = LOWORD(nRegSize); } if ((nFontX > curSizeX) || (nFontY > curSizeY)) { apiSetConsoleFontSize(hOutput, nFontY, nFontX, sFontName); } } } } } }
// Vista+ only BOOL apiFixFontSizeForBufferSize(HANDLE hOutput, COORD dwSize, char* pszUtfLog /*= NULL*/, int cchLogMax /*= 0*/) { BOOL lbRetry = FALSE; CONSOLE_SCREEN_BUFFER_INFO csbi = {}; if (pszUtfLog) *pszUtfLog = 0; if (dwSize.Y > 0 && dwSize.X > 0 && GetConsoleScreenBufferInfo(hOutput, &csbi)) { COORD crLargest = MyGetLargestConsoleWindowSize(hOutput); int nMaxX = GetSystemMetrics(SM_CXFULLSCREEN); int nMaxY = GetSystemMetrics(SM_CYFULLSCREEN); #ifdef _DEBUG // Для отладки, смотрим какой размер получится по crLargest int nDbgFontX = crLargest.X ? (nMaxX / crLargest.X) : -1; int nDbgFontY = crLargest.Y ? (nMaxY / crLargest.Y) : -1; #endif int curSizeY, curSizeX, newSizeY, newSizeX, calcSizeY, calcSizeX; wchar_t sFontName[LF_FACESIZE]; if (apiGetConsoleFontSize(hOutput, curSizeY, curSizeX, sFontName) && curSizeY && curSizeX) { // Увеличение if (crLargest.X && crLargest.Y && ((dwSize.X > crLargest.X) || (dwSize.Y > crLargest.Y))) { // Теперь прикинуть, какой размер шрифта нам нужен newSizeY = max(1,(nMaxY / (dwSize.Y+1))); newSizeX = max(1,(nMaxX / (dwSize.X+1))); if ((newSizeY < curSizeY) || (newSizeX < curSizeX)) { calcSizeX = newSizeY * curSizeX / curSizeY; calcSizeY = newSizeX * curSizeY / curSizeX; if (calcSizeY < curSizeY) calcSizeX = min(calcSizeX,(calcSizeY * curSizeX / curSizeY)); if (calcSizeX < curSizeX) calcSizeY = min(calcSizeY,(calcSizeX * curSizeY / curSizeX)); newSizeY = max(1,min(calcSizeY,curSizeY)); newSizeX = max(1,min(calcSizeX,curSizeX)); lbRetry = TRUE; } } // Уменьшение else if ((dwSize.X <= (csbi.srWindow.Right - csbi.srWindow.Left)) || (dwSize.Y <= (csbi.srWindow.Bottom - csbi.srWindow.Top))) { int nMinY = GetSystemMetrics(SM_CYMIN) - GetSystemMetrics(SM_CYSIZEFRAME) - GetSystemMetrics(SM_CYCAPTION); int nMinX = GetSystemMetrics(SM_CXMIN) - 2*GetSystemMetrics(SM_CXSIZEFRAME); if ((nMinX > 0) && (nMinY > 0)) { // Теперь прикинуть, какой размер шрифта нам нужен newSizeY = (nMinY / (dwSize.Y)) + 1; // Win8. На базовых настройках разбиение консоли дважды по Ctrl+Shift+O // дает ошибку - размер шрифта в третьей консоли оказывается недостаточным newSizeX = (nMinX / (dwSize.X)) + 2; if ((newSizeY > curSizeY) || (newSizeX > curSizeX)) { calcSizeX = newSizeY * curSizeX / curSizeY; calcSizeY = newSizeX * curSizeY / curSizeX; if (calcSizeY > curSizeY) calcSizeX = max(calcSizeX,(calcSizeY * curSizeX / curSizeY)); if (calcSizeX > curSizeX) calcSizeY = max(calcSizeY,(calcSizeX * curSizeY / curSizeX)); newSizeY = max(calcSizeY,curSizeY); newSizeX = max(calcSizeX,curSizeX); lbRetry = TRUE; } } } if (lbRetry) { lbRetry = apiSetConsoleFontSize(hOutput, newSizeY, newSizeX, sFontName); } } } return lbRetry; }
void SetUserFriendlyFont(HWND hConWnd, int newFontY = 0, int newFontX = 0) { // Соответствующие функции появились только в API Vista // Win2k & WinXP - доступны только хаки, что не подходит _ASSERTE(_WIN32_WINNT_VISTA==0x600); OSVERSIONINFOEXW osvi = {sizeof(osvi), HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA)}; DWORDLONG const dwlConditionMask = VerSetConditionMask(VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL), VER_MINORVERSION, VER_GREATER_EQUAL); if (!VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask)) return; HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); COORD crVisibleSize = {}; CONSOLE_SCREEN_BUFFER_INFO csbi = {}; if (GetConsoleScreenBufferInfo(hOutput, &csbi)) { crVisibleSize.X = csbi.srWindow.Right - csbi.srWindow.Left + 1; crVisibleSize.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; } if ((crVisibleSize.X <= 0) || (crVisibleSize.Y <= 0)) { _ASSERTE((crVisibleSize.X > 0) && (crVisibleSize.Y > 0)); return; } int curSizeY = 0, curSizeX = 0; wchar_t sFontName[LF_FACESIZE] = L""; if (apiGetConsoleFontSize(hOutput, curSizeY, curSizeX, sFontName) && curSizeY && curSizeX) { if (newFontY <= 0 || newFontX <= 0) { DEBUGTEST(COORD crLargest = MyGetLargestConsoleWindowSize(hOutput)); HMONITOR hMon = MonitorFromWindow(hConWnd, MONITOR_DEFAULTTOPRIMARY); MONITORINFO mi = {sizeof(mi)}; int nMaxX = 0, nMaxY = 0; if (GetMonitorInfo(hMon, &mi)) { nMaxX = mi.rcWork.right - mi.rcWork.left - 2*GetSystemMetrics(SM_CXSIZEFRAME) - GetSystemMetrics(SM_CYCAPTION); nMaxY = mi.rcWork.bottom - mi.rcWork.top - 2*GetSystemMetrics(SM_CYSIZEFRAME); } if ((nMaxX > 0) && (nMaxY > 0)) { int nFontX = nMaxX / crVisibleSize.X; int nFontY = nMaxY / crVisibleSize.Y; // Too large height? if (nFontY > 28) { nFontX = 28 * nFontX / nFontY; nFontY = 28; } // Evaluate default width for the font int nEvalX = EvaluateDefaultFontWidth(nFontY, sFontName); if (nEvalX > 0) { if ((nEvalX > nFontX) && (nFontX > 0)) nFontY = nFontX * nFontY / nEvalX; else nFontX = nEvalX; } // Look in the registry? HKEY hk; DWORD nRegSize = 0, nLen; if (!RegOpenKeyEx(HKEY_CURRENT_USER, L"Console", 0, KEY_READ, &hk)) { if (RegQueryValueEx(hk, L"FontSize", NULL, NULL, (LPBYTE)&nRegSize, &(nLen=sizeof(nRegSize))) || nLen!=sizeof(nRegSize)) nRegSize = 0; RegCloseKey(hk); } if (!nRegSize && !RegOpenKeyEx(HKEY_CURRENT_USER, L"Console\\%SystemRoot%_system32_cmd.exe", 0, KEY_READ, &hk)) { if (RegQueryValueEx(hk, L"FontSize", NULL, NULL, (LPBYTE)&nRegSize, &(nLen=sizeof(nRegSize))) || nLen!=sizeof(nRegSize)) nRegSize = 0; RegCloseKey(hk); } if ((HIWORD(nRegSize) > curSizeY) && (HIWORD(nRegSize) < nFontY) && (LOWORD(nRegSize) > curSizeX) && (LOWORD(nRegSize) < nFontX)) { nFontY = HIWORD(nRegSize); nFontX = LOWORD(nRegSize); } if ((nFontX > curSizeX) || (nFontY > curSizeY)) { newFontY = nFontY; newFontX = nFontX; } } } } if ((newFontY > 0) && (newFontX > 0)) { if (!*sFontName) lstrcpyn(sFontName, L"Lucida Console", countof(sFontName)); apiSetConsoleFontSize(hOutput, newFontY, newFontX, sFontName); } }