ホーム » Windows (ページ 4)
「Windows」カテゴリーアーカイブ
@MS PGothic の高さ方向の間隔
以前から気になっていたことだが,文字列を縦書きにした時重なってしまうことがある.
文字ごとに ::GetGlyphOutline を呼出して,位置をずらしている( += gm.gmCellIncX ).
gmptGlyphOrigin を使えばよいのかもしれないが,テストした限りではうまくできなかった.
更にいろいろと試していると,LOGFONT の文字の高さを 23 より大きくするとうまくいく.
また,他のプロポーショナルフォントではうまくいくものもが多い.
::IsFontInstalled (LPCTSTR pszFace)
EnumFont… を調べていて,::IsFontInstalled を見つけた.
MFC 6 位に追加されたみたいだが,static 宣言されている.
VC 6 RTM では存在していなさそう.
正確なタイミングはわからないが,VC 6 SP6 には存在していて …\MFC\SRC\CCDATA.CPP にある,
フォントがインストールされているかのチェックに利用できそうなので,関数として定義予定.
CComboBox Get…Text() ?
CComboBox の選択項目の取得には GetLBText がある.
が,エディットボックス部分の取得方法がそこには書かれていない?
検索しても,あまりうまく引っかからない.
::GetWindowText(m_CtrlComboBox.GetSafeHwnd(),…) でいけそうなことは確認した.
Spy++ で見ると,エディットボックスの部分は「子ウィンドウ」になっている?
いろいろと調べると次の様なものもあり.
WindowsX.h
#define ComboBox_GetText(hwndCtl, lpch, cchMax) GetWindowText((hwndCtl), (lpch), (cchMax))
CComboBox の DDX_CBString を追加して,デバッガで追いかけると,::GetWindowText を呼出している.
MFC による Windows 95 プログラミングの 358 ページに次の様にあった.
コンボボックスの操作
… CWnd から継承している GetWindowText,SetWindowText 関数は,予想通り,エディットコントロール内のテキストを取得,設定する.
MFC だと次の様にできる.
CString str ;
m_CtrlComboBox.GetWindowText(str) ;
EnumFontFam…Proc
CALLBACK で呼び出されたものを FontType で分類して文字列の配列に登録.
#include <Windows.h>
class EnumFont {
public:
static int CALLBACK CB_EnumFontFam (const ENUMLOGFONT* lpelf_,const NEWTEXTMETRIC* lpntm_,DWORD font_type,LPARAM lparam) ;
static int CALLBACK CB_EnumFontFamEx (const ENUMLOGFONTEX* lpelfe,const NEWTEXTMETRICEX* lpntme,DWORD font_type,LPARAM lparam) ;
protected:
public:
v_tstring Font_________ ; // 0
v_tstring Font_raster__ ; // 1 RASTER_FONTTYPE
v_tstring Font_device__ ; // 2 DEVICE_FONTTYPE
v_tstring Font_truetype ; // 4 TRUETYPE_FONTTYPE
} ;
inline int CALLBACK EnumFont::CB_EnumFontFam (const ENUMLOGFONT* lpelf_,const NEWTEXTMETRIC* lpntm_,DWORD font_type,LPARAM p_this)
{
const LOGFONT& lf = lpelf_->elfLogFont ;
EnumFont* pthis = (EnumFont*)p_this ;
if (font_type & RASTER_FONTTYPE) { pthis->Font_raster__.push_back(lf.lfFaceName) ; }
else if (font_type & TRUETYPE_FONTTYPE) { pthis->Font_truetype.push_back(lf.lfFaceName) ; }
else if (font_type & DEVICE_FONTTYPE) { pthis->Font_device__.push_back(lf.lfFaceName) ; }
else { pthis->Font_________.push_back(lf.lfFaceName) ; }
return 1 ;
}
inline int CALLBACK EnumFont::CB_EnumFontFamEx (const ENUMLOGFONTEX* lpelfe,const NEWTEXTMETRICEX* lpntme,DWORD font_type,LPARAM p_this)
{
const LOGFONT& lf = lpelfe->elfLogFont ;
EnumFont* pthis = (EnumFont*)p_this ;
if (font_type & RASTER_FONTTYPE) { pthis->Font_raster__.push_back(lf.lfFaceName) ; }
else if (font_type & TRUETYPE_FONTTYPE) { pthis->Font_truetype.push_back(lf.lfFaceName) ; }
else if (font_type & DEVICE_FONTTYPE) { pthis->Font_device__.push_back(lf.lfFaceName) ; }
else { pthis->Font_________.push_back(lf.lfFaceName) ; }
return 1 ;
}
次の様に呼出し.
bool test (void)
{
HWND hWnd = ::GetConsoleWindow() ;
HDC hdc = ::GetDC(hWnd);
{
EnumFont ef_ ;
EnumFont efe ;
{
::EnumFontFamilies (hdc,NULL,(FONTENUMPROC)EnumFont::CB_EnumFontFam, (LPARAM)&ef_) ;
::EnumFontFamiliesEx(hdc,NULL,(FONTENUMPROC)EnumFont::CB_EnumFontFamEx,(LPARAM)&efe,0) ;
}
{
tstring tmp_path = ::Get_i_Tools_tmp_date() ;
tstring fet_name = ::Path_AddLastSP(tmp_path) + ::Now_Format(_T("%H%M%S")) + _T("_ffe_t.txt") ;
tstring fer_name = ::Path_AddLastSP(tmp_path) + ::Now_Format(_T("%H%M%S")) + _T("_ffe_r.txt") ;
tstring fed_name = ::Path_AddLastSP(tmp_path) + ::Now_Format(_T("%H%M%S")) + _T("_ffe_d.txt") ;
tstring fe__name = ::Path_AddLastSP(tmp_path) + ::Now_Format(_T("%H%M%S")) + _T("_ffe__.txt") ;
tstring f_t_name = ::Path_AddLastSP(tmp_path) + ::Now_Format(_T("%H%M%S")) + _T("_ff__t.txt") ;
tstring f_r_name = ::Path_AddLastSP(tmp_path) + ::Now_Format(_T("%H%M%S")) + _T("_ff__r.txt") ;
tstring f_d_name = ::Path_AddLastSP(tmp_path) + ::Now_Format(_T("%H%M%S")) + _T("_ff__d.txt") ;
tstring f___name = ::Path_AddLastSP(tmp_path) + ::Now_Format(_T("%H%M%S")) + _T("_ff___.txt") ;
::SaveText(fet_name.c_str(),efe.Font_truetype) ;
::SaveText(fer_name.c_str(),efe.Font_raster__) ;
::SaveText(fed_name.c_str(),efe.Font_device__) ;
::SaveText(fe__name.c_str(),efe.Font_________) ;
::SaveText(f_t_name.c_str(),ef_.Font_truetype) ;
::SaveText(f_r_name.c_str(),ef_.Font_raster__) ;
::SaveText(f_d_name.c_str(),ef_.Font_device__) ;
::SaveText(f___name.c_str(),ef_.Font_________) ;
}
}
::ReleaseDC(NULL,hdc);
return true ;
}
::EnumFont…
幾つかの所で使用している ::EnumFont … と フォント 選択 .
最近追加したフォントでうまく列挙されないものがある.
先日試したコード では列挙されているので,コールバック関数の部分がうまくない.
フォントを列挙する部分は 20 年以上前に書いたコード.
間違ってはなさそうだが,MFC に依存しているので見直すことに.
プログラミング Windows 第5版 を見たが,1 ページ程度.
::EnumFonts , ::EnumFontFamilies , ::EnumFontFamiliesEx の違いなどが簡単に書かれている.
当時参考にしたのは,MFC による Windows 95 プログラミング だったみたい.ソースにコメントが残っていた.
コールバック関数の EnumFontFamExProc が呼ばれるのは,::EnumFontFamiliesEx が呼ばれた直後.
AfxGetInstanceHandle
コンソール AP を変更していて「MFC を使用」にすると AfxGetInstanceHandle で ASSERT .
---------------------------
Microsoft Visual C++ Debug Library
---------------------------
Debug Assertion Failed!
Program: c:\Temp\TOutline\tolmba\Debug.060\tolmba.exe
File: afxwin1.inl
Line: 19
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
---------------------------
中止(A) 再試行(R) 無視(I)
---------------------------
この単体テスト用プロジェクトは,最初 MFC を使用しないでコードを書いていた.
が,幾つかの機能を付けていくと MFC を使用した既存のコードが必要になった.
その中で AfxGetInstanceHandle() を呼出している所があり,そこで ASSERT .
次の様に MFC の初期化 ::AfxWinInit を追加して対応.
int _tmain (int argc,TCHAR* argv[])
{
#ifdef _MFC_VER
if (!::AfxWinInit(::GetModuleHandle(NULL),NULL,::GetCommandLine(),0)) {
return 1 ;
}
#endif
_tsetlocale(LC_ALL,_T("")) ;
// ...
return 0 ;
}
::EnumFontFamilies…
フォントを列挙する方法を「ChatGPT」と「Bingチャット」で問合わせてみた.
ChatGPT
#include <windows.h>
#include <iostream>
int main() {
HDC hdc = GetDC(NULL);
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
lf.lfCharSet = DEFAULT_CHARSET;
std::cout << "Available Fonts:" << std::endl;
EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)EnumFontFamiliesCallback, 0, 0);
ReleaseDC(NULL, hdc);
return 0;
}
int CALLBACK EnumFontFamiliesCallback(ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme, DWORD FontType, LPARAM lParam) {
std::cout << lpelfe->elfFullName << std::endl;
return 1;
}
Bingチャット
#include <windows.h>
#include <iostream>
#include <string>
int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXW* lpelfe, NEWTEXTMETRICEXW* lpntme, DWORD FontType, LPARAM lParam)
{
std::wcout << lpelfe->elfFullName << std::endl;
return 1;
}
int main()
{
HDC hdc = GetDC(NULL);
LOGFONTW lf = { 0 };
lf.lfCharSet = DEFAULT_CHARSET;
EnumFontFamiliesExW(hdc, &lf, (FONTENUMPROCW)EnumFontFamExProc, 0, 0);
ReleaseDC(NULL, hdc);
return 0;
}
WebGL での 3D データ表示
さらに,以前作成した Web サーバ を利用して WebGL での表示に.
bool test (void)
{
Vd2A pts ;
{
pts.push_back(Vd2( 0, 0)) ;
pts.push_back(Vd2( 70, 0)) ;
pts.push_back(Vd2( 90, 50)) ;
pts.push_back(Vd2(100,100)) ;
pts.push_back(Vd2( 50,100)) ;
pts.push_back(Vd2( 30, 70)) ;
pts.push_back(Vd2( 40, 30)) ;
pts.push_back(Vd2( 0, 0)) ;
}
vv_PLF vvplf ;
{
Vd3A v3a = ::ToVd3A(pts) ;
Vd4A v4a = ::ToVd4A(v3a) ;
PLF plf_l(PLF::line,v4a) ;
PLF plf_f(PLF::face,v4a) ;
v_PLF v_plf ;
v_plf.push_back(plf_l) ;
v_plf.push_back(plf_f) ;
vvplf.push_back(v_plf) ;
}
{
tstring tmp_path = ::Get_i_Tools_tmp_date() ;
tstring out_name = ::Path_AddLastSP(tmp_path) + ::Now_Format(_T("%H%M%S")) + _T("__.htm") ;
tstring outtname = ::Path_AddLastSP(tmp_path) + ::Now_Format(_T("%H%M%S")) + _T("_t.htm") ;
tstring outnname = ::Path_AddLastSP(tmp_path) + ::Now_Format(_T("%H%M%S")) + _T("_n.htm") ;
{
GonsA gnsa = ::PLF_ToGonsA(vvplf) ;
::GonsA_ToWGL(gnsa,out_name.c_str()) ;
gnsa = ::GonsA_Triangulation(gnsa) ;
::GonsA_ToWGL(gnsa,outtname.c_str()) ;
gnsa = ::GonsA_CalcNormal (gnsa) ;
::GonsA_ToWGL(gnsa,outnname.c_str()) ;
}
{
::start_web_server(tmp_path) ;
}
}
tstring g3_d_exe = ::get_g3_d_exe() ;
if (!g3_d_exe.empty()) {
tstring tmp_path = ::Get_i_Tools_tmp_date() ;
tstring ipl_name = ::Path_AddLastSP(tmp_path) + ::Now_Format(_T("%H%M%S")) + _T(".ipl") ;
::To_ipl (vvplf,ipl_name.c_str()) ;
::start_g3_d(ipl_name.c_str()) ;
}
return true ;
}
Linux での GLUT 3D データ表示
昨日のコードをもう少し汎用的に修正.そしてそれを他から呼出せるように変更.
次の様なコードで 3D データを生成して,GLUT で表示できる様にした.
bool test (void)
{
Vd2A pts ;
{
pts.push_back(Vd2( 0, 0)) ;
pts.push_back(Vd2( 70, 0)) ;
pts.push_back(Vd2( 90, 50)) ;
pts.push_back(Vd2(100,100)) ;
pts.push_back(Vd2( 50,100)) ;
pts.push_back(Vd2( 30, 70)) ;
pts.push_back(Vd2( 40, 30)) ;
pts.push_back(Vd2( 0, 0)) ;
}
vv_PLF vvplf ;
{
Vd3A v3a = ::ToVd3A(pts) ;
Vd4A v4a = ::ToVd4A(v3a) ;
PLF plf_l__ (PLF::line,v4a) ;
PLF plf_f__ (PLF::face,v4a) ;
v_PLF v_plf ;
v_plf.push_back(plf_l__) ;
v_plf.push_back(plf_f__) ;
vvplf.push_back(v_plf) ;
}
tstring txt_name = ::g3_d_get_txt_name() ;
{
tstring tmp_path = ::Get_i_Tools_tmp_date() ;
tstring ipl_name = ::Path_AddLastSP(tmp_path) + ::Now_Format(_T("%H%M%S")) + _T(".ipl") ;
::To_ipl (vvplf,ipl_name.c_str()) ;
::SaveText(txt_name.c_str(),ipl_name) ;
}
{
::exec_g3_d(txt_name.c_str()) ;
}
return true ;
}
GLUT を使用した 3D データの表示
個人的なメモです.
4 年位前に作成したコードで,凹多角形がうまく処理できていないものがあったのでその変更.
#include "glut_cg.hxx"
#include "gonsa_to.hxx"
#define TIMING_DN 1000
// int _tmain (int argc, _TCHAR* argv[])
int main (int argc, char* argv[])
{
{
GonsA gnsa ;
{
tstring buf ; buf.resize(1000) ;
while (std::terr << _T("file ? =") , std::tin.getline(&buf[0],buf.size()))
{
tstring str = buf.c_str() ;
if (str == _T("q")) { break ; }
else if (str == _T("Q")) { break ; }
str = ::QuotM_Del_All(str) ;
if (str.empty()) { continue ; }
if (::File_IsNothing(str)) { continue ; }
tstring in_file = str ;
gnsa = ::To_GonsA(in_file.c_str()) ;
gnsa = ::GonsA_Triangulation(gnsa) ; // 2023/06/27
gnsa = ::GonsA_CalcNormal (gnsa) ; // 2023/06/27
if (gnsa.size() > 0) { break ; }
}
if (gnsa.size() == 0) { return 0 ; }
}
::set_GonsA(gnsa) ;
::set_Extent(::GonsA_GetExtent(gnsa)) ;
}
::glutInitWindowPosition(200,200) ;
::glutInitWindowSize (600,400) ;
::glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH) ;
::glutInit (&argc,argv) ;
::glutCreateWindow (argv[0]) ;
::glutReshapeFunc (cv_resize) ;
::glutDisplayFunc (cg_display) ;
::glutKeyboardFunc (cv_keyboard) ;
::glutMouseFunc (cv_mouse) ;
::glutMotionFunc (cv_motion) ;
::glutTimerFunc (TIMING_DN,cv_timer,TIMING_DN) ;
::cv_init () ;
{
::glEnable(GL_LIGHTING) ;
::glEnable(GL_LIGHT0) ;
}
::glutMainLoop () ;
return 0 ;
}
#include "messbar.cxx"
warning C4305:
先日次の様なコードを書いていた.塗りつぶして表示する時の色の補正.
ColorRGB colRGB = ::ColorRefToRGB(pgs1.GetColor()) ;
{
float rgbcol = colRGB.R + colRGB.G + colRGB.B ;
if (rgbcol < 0.20*3) {
if (colRGB.R < 0.20) { colRGB.R = 0.20f ; }
if (colRGB.G < 0.20) { colRGB.G = 0.20f ; }
if (colRGB.B < 0.20) { colRGB.B = 0.20f ; }
}
if (0.80*3 < rgbcol) {
if (0.80 < colRGB.R) { colRGB.R = 0.80f ; }
if (0.80 < colRGB.G) { colRGB.G = 0.80f ; }
if (0.80 < colRGB.B) { colRGB.B = 0.80f ; }
}
}
ColorRGB.R などは float で,RGB のそれぞれを 0.0 ~ 1.0 で表現したもの.
最初 if (colRGB.R < 0.25) { colRGB.R = 0.25 ; } の様にしていたが,0.2 に変更した.
すると C4305 の warning .0.2f の様にすれば良いのはわかっているが,他の値で調べてみた.
0.0 , 1.0 , 7.0 などは大丈夫だが,0.2 や 7.1 は C4305 になってしまう.
コンパイラやオプションの指定にもよると思うが,float で表現できない場合のみ warning となるのか?
SetForegroundWindow
他 AP から,HWND を指定して前面に移動する方法.
bool Window_Foreground (HWND hWnd)
{
if (hWnd == NULL) { return false ; }
if (!::IsWindow(hWnd)) { return false ; }
{
if (::IsIconic(hWnd)) {
WINDOWPLACEMENT wndpl = { 0 } ;
::GetWindowPlacement(hWnd,&wndpl) ;
wndpl.showCmd = SW_RESTORE ;
::SetWindowPlacement(hWnd,&wndpl) ;
}
SetForegroundWindow(hWnd) ;
}
return true ;
}
VC 2022 17.6.?
先日 VS 2022 の更新版 があったのでアップデート.
個人的なツールの 3D ビューア をビルドすると,
ALYac Gen:Variant.Tedy.373496
Arcabit Trojan.Tedy.D5B2F8
BitDefender Gen:Variant.Tedy.373496
Cylance Unsafe
DeepInstinct MALICIOUS
Emsisoft Gen:Variant.Tedy.373496 (B)
eScan Gen:Variant.Tedy.373496
GData Gen:Variant.Tedy.373496
MAX Malware (ai Score=81)
McAfee Artemis!AE3A9CE560AE
McAfee-GW-Edition Artemis
Trellix (FireEye) Gen:Variant.Tedy.373496
TrendMicro-HouseCall TROJ_GEN.R002H09EQ23
VIPRE Gen:Variant.Tedy.373496
VC 2019 などでビルドしたものは問題ない.また VC 2022 更新前のものも問題なかった.
今まで VS の更新版が出てすぐにそれでビルドすることは少なかった.
テストが不十分なこともあり,リリース用は主に VC 2017 を使用している.
更新版によっては,この様なことがあるのかもしれない.
落ち着くまでしばらく時間がかかるのか?
error during ReadSymbolTable
5 年位前に作成したプロジェクトをビルドしていると,
--------------------Configuration: phpup_mb - Win32 Debug--------------------
Compiling...
ComPrj01.cpp
phpup_mb.cpp
...
Linking...
c:\Temp\HTM\phpup\phpup_mb\Debug.060\ComPrj01.obj : error : Internal error during ReadSymbolTable
ExceptionCode = C0000005
ExceptionFlags = 00000000
ExceptionAddress = 004623F2
NumberParameters = 00000002
ExceptionInformation[ 0] = 00000000
ExceptionInformation[ 1] = 0090B470
CONTEXT:
Eax = 3FFF1E64 Esp = 0019F050
Ebx = FFFF8000 Ebp = 01B834C7
Ecx = 3FFF1E64 Esi = 401F1EC0
Edx = 0094B478 Edi = 401F1EC0
Eip = 004623F2 EFlags = 00010246
SegCs = 00000023 SegDs = 0000002B
SegSs = 0000002B SegEs = 0000002B
SegFs = 00000053 SegGs = 0000002B
Dr0 = 0019F050 Dr3 = FFFF8000
Dr1 = 01B834C7 Dr6 = 3FFF1E64
Dr2 = 00000000 Dr7 = 00000000
Error executing link.exe.
Tool execution canceled by user.
exe は存在するが正しくできていないので,exe のみ削除して再度ビルド.
--------------------Configuration: phpup_mb - Win32 Debug--------------------
Linking...
LINK : LNK6004: c:\Temp\HTM\phpup\phpup_mb\Debug.060/phpup_mb.exe not found or not built by the last incremental link; performing full link
ComPrj01.obj : fatal error LNK1143: invalid or corrupt file: no symbol for comdat section 0xffff8000
Error executing link.exe.
phpup_mb.exe - 1 error(s), 0 warning(s)
obj のサイズを見ると,20 MB 位になっている.
それで思い出したのが,前にも同じ様な現象が…
LNK1143 : ファイルが無効であるか…
ソースを分割して対応.
CComboBox::SetItemHeight (-1,…)
高 DPI 対応で修正していて,コンボボックス(特に,オーナードロー?)の高さが他に比べて不自然.
ドキュメントを見ると,CB_SETITEMHEIGHT と思うが,指定方法がよくわからない.
「コンボボックス 高さ 変更」で 検索する と「できない」と記述されている所もある.
CB_SETITEMHEIGHT で検索していると,-1 を指定しているものがある.
さらに,CB_GETITEMHEIGHT のドキュメントを見ると,次の様にある.
選択フィールドの高さを取得するには、このパラメーターは -1 である必要があります
どうも CB_SETITEMHEIGHT の表現がうまくないものと思う.
次の様なコードで対応.
{
CRect rect ;
m_CtrlStrText.GetClientRect(&rect) ;
FontFace.SendMessage(CB_SETITEMHEIGHT,-1,rect.Height()) ;
FontFace.SendMessage(CB_SETITEMHEIGHT, 0,rect.Height()*15/10) ;
}
2023/05/16
ドロップダウンの幅がうまくなかったが,共通コードを見るといろいろ考慮しなければならない部分が多い.
そのため,次の様なコードで対応.
{
new_w = now_w ;
// new_w = now_w * 15 / 10 ;
new_w = int(new_w * ::GetDPI_scale(this->GetSafeHwnd())) ; // new_w*(::GetDpiForWindow()/96.)
FontFace.SendMessage(CB_SETDROPPEDWIDTH,new_w) ;
}
間違っているかもしれないが,CB_SETITEMHEIGHT を簡単にテストしたことのまとめ.
通常のコンボボックスの場合 | -1 で,全ての項目の高さを設定できる |
オーナードロー 固定 | -1 で,エディットボックス部分の高さを指定 0 で,ドロップ部分の項目の高さを指定 |
オーナードロー 可変 | -1 で,エディットボックス部分の高さを指定 0 以上で,ドロップ部分のそれぞれの高さを指定 |
VirtualBox PXE-E06
Win11 上の仮想マシン Win10 の Windows Update での再起動で,
PXE-E06: Option ROM requires DDIM support.
検索してみた が,あまりいい情報に引っ掛からない.
Windows Update での再起動だったので心配だったが,仮想マシンを一度 OFF して,再起動.
特に何もなかったかの様に起動した.
何だったのだろう.
2024/04/05
その後頻繁にこの現象が発生する.VirtualBox と Windows との相性か?
高 DPI VC 「高い DPI 認識」
引き続きいろいろとやっているが…
異なる DPI での対応は簡単ではなさそう.
VC のプロパティで「モニターごと高い DPI 認識」としてビルドしていたが,モニタ間を移動するとうまくない.
ちゃんと対応すれば良いのだろうが,簡単ではない.
そのため exe のプロパティで「システム(拡張)」で良いと思っていたが,幾つかのバグ?(未対応)がある.
VC のプロパティで「高い DPI 認識」にしてビルドしたものの方がうまく機能している様な気がする.
左から VC 10 ,14 ,10 ,14 としたもの.
タスクマネージャで見ると,VC 10 exe は「システム」として表示される.
左側のモニタの範囲は次の様になる.
-1920 130 0 1210 100% 1920 1080 「非対応」や「モニタごと」の場合
-3840 260 0 2420 200% 3840 2160 「システム」とした exe の場合
右側は ( 0 , 0 ) – ( 3840 , 2160 ) .
GDI スケーリングの動作として,次の記述があった.
アプリケーションが 100% (96 DPI) の倍数ではないディスプレイで実行されている場合、ベクター グラフィックスとテキストは、ディスプレイの倍率より 100% 高い最初の整数倍にレンダリングされます。たとえば、アプリケーションが 225% の縮尺のディスプレイ上にある場合、ベクター グラフィックスとビットマップは 300% でレンダリングされます。その後、DWM はレンダリングされたコンテンツを 225% のスケールに縮小します。この場合、スケールダウンによりアプリケーションのあいまいさが目立ちますが、100%レンダリングされたコンテンツを単純にスケールアップするよりも見栄えが良くなります。
Improving the high-DPI experience in GDI based Desktop Apps
How to build high DPI aware native Windows desktop applications
2023/05/12
「システム(拡張)」で幾つか変な動作があったが,「高い DPI 認識」でビルドしたものであれば良さそう.
C++ 戻り値の異なる関数 template
先日からやっている .ini やレジストリにアクセスする関数.
MFC の CWinApp::GetProfileString , CWinApp::WriteProfileString にあたる部分は目途がついた.
それで,それらを呼出す部分.前に作成したものもそうだったが,型ごとにクラスの関数を定義していた.
これらをもう少し簡単にできないかと…
set の方は,特に難しい所はない(::To_tstring は,文字列に変換する関数として用意している).
template <class T> bool INI_set (LPCTSTR sec,LPCTSTR ent,const T& val)
{
tstring ini = ::INI_get_module_ini() ;
tstring str = ::To_tstring(val) ;
return ::INI_set(ini.c_str(),sec,ent,str.c_str()) ;
}
get の場合,文字列から変数に変換する方法をどうするか?
例えば,atoi や atof ,他にも 4 つの整数の文字列を RECT に変換するなど.
検索すると template で可能みたい だが…
よくわからなかったので,簡単な方法にした.
inline RECT To_RECT (LPCTSTR str)
{
RECT rect = { 0 } ;
{
v_tstring str_ary = ::String_SplitSpace(str,_T(" ,\t\r\n")) ;
if (0 < str_ary.size()) { rect.left = ::ttoi4(str_ary[0]) ; }
if (1 < str_ary.size()) { rect.top = ::ttoi4(str_ary[1]) ; }
if (2 < str_ary.size()) { rect.right = ::ttoi4(str_ary[2]) ; }
if (3 < str_ary.size()) { rect.bottom = ::ttoi4(str_ary[3]) ; }
}
return rect ;
}
inline bool string_to (LPCTSTR str,RECT* rect_) { *rect_ = ::To_RECT (str) ; return true ; }
inline bool string_to (LPCTSTR str,POINT* point) { *point = ::To_POINT(str) ; return true ; }
inline bool string_to (LPCTSTR str,SIZE* size_) { *size_ = ::To_SIZE (str) ; return true ; }
それぞれの型に合わせた関数を呼べるようになったので template に.
template <class T> T INI_get (LPCTSTR sec,LPCTSTR ent,const T& def)
{
tstring ini = ::INI_get_module_ini() ;
tstring dst = ::To_tstring(def) ;
tstring str = ::INI_get(ini.c_str(),sec,ent,dst.c_str()) ;
T val ;
::string_to(str.c_str(),&val) ;
return val ;
}
これで,次の様な使い方ができる様になる.
{
POINT point = ::POINT_set( 10, 20) ;
SIZE size_ = :: SIZE_set( 1111, 525) ;
RECT rect_ = :: RECT_set(point,size_) ;
{
::INI_set(_T("test"),_T("rect_"),rect_) ;
::INI_set(_T("test"),_T("point"),point) ;
::INI_set(_T("test"),_T("size_"),size_) ;
std::tout << ::To_tstring(::INI_get(_T("test"),_T("rect_"),rect_)) << std::endl ;
std::tout << ::To_tstring(::INI_get(_T("test"),_T("point"),point)) << std::endl ;
std::tout << ::To_tstring(::INI_get(_T("test"),_T("size_"),size_)) << std::endl ;
}
}
RegOpenKeyEx REGSAM
レジストリアクセスのコードを書き直していて,::RegOpenKeyEx の samDesired を調べてみた.
KEY_READ (0x20019) 0010 0000 0000 0001 1001
KEY_WRITE (0x20006) 0010 0000 0000 0000 0110
KEY_EXECUTE (0x20019) 0010 0000 0000 0001 1001
KEY_QUERY_VALUE (0x0001) 0000 0000 0000 0001
KEY_SET_VALUE (0x0002) 0000 0000 0000 0010
KEY_CREATE_SUB_KEY (0x0004) 0000 0000 0000 0100
KEY_ENUMERATE_SUB_KEYS (0x0008) 0000 0000 0000 1000
KEY_NOTIFY (0x0010) 0000 0000 0001 0000
KEY_CREATE_LINK (0x0020) 0000 0000 0010 0000
KEY_WOW64_64KEY (0x0100) 0000 0001 0000 0000
KEY_WOW64_32KEY (0x0200) 0000 0010 0000 0000
KEY_ALL_ACCESS (0xF003F) 1111 0000 0000 0011 1111
読み込み時,KEY_READ の方が速いなどはあるのか?それともファイルアクセスなどと同じ?