ホーム » VC (ページ 2)

VC」カテゴリーアーカイブ

2024年4月
 123456
78910111213
14151617181920
21222324252627
282930  

カテゴリー

アーカイブ

ブログ統計情報

  • 79,418 アクセス



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 ;
		}
	}

::INI_set ,::INI_get の動作テスト

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

C++ NonCopyable

MFC を使用しないコードに書き直していて,代入できない構造体が欲しくなった.
オリジナルのコードは 20 年以上前のもので,CRegKey が簡単には使えなかった?頃.


C++ クラス 代入できなくする」で検索.
コピー禁止を徹底させるNoncopyableクラス
More C++ Idioms/コピー禁止ミックスイン(Non-copyable Mixin)
明示的に既定された関数および削除された関数
MFC の CObject も同様と思いソースを見ると,やはり private になっている.
MFC CObject 代入の禁止
C++11 以降では =delete も使える.
関数のdefault/delete宣言
wiki C++11


これらを調べていて,次の所を見つけた.
旧時代のC言語を使うのはそろそろやめよう。
2016年、C言語はどう書くべきか (前編)
2016年、C言語はどう書くべきか (後編)
幾つかは既に意識しているが,Windows に依存する部分はなかなかできてない.

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

RegOpenKeyEx REGSAM

レジストリアクセスのコードを書き直していて,::RegOpenKeyExsamDesired を調べてみた.

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

ソースを見た方が早かったか?
RegOpenKeyEx REGSAM


読み込み時,KEY_READ の方が速いなどはあるのか?それともファイルアクセスなどと同じ?

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

GetMonitorInfo

2002/08 に,マルチディスプレイ対応のコードを書いている.
今回,高 DPI 対応やディスプレイ位置が変わった時などのためもう一度…


ChatGPT で.
ChatGPT  GetMonitorInfo 使い方サンプル
そのままでは VC 6 ではうまくビルドできなかったので,VC 8 で.
printf を使用しているので #include <cstdio> が必要.
そのまま実行すると 1920×1080 となる.
GetMonitorInfo
高 DPI スケール設定を「アプリケーション」とすると,3840×2160 .


2023/04/14
以前のコードを見ると,プライマリのみの情報は ::SystemParametersInfo などを使用している.
これで求められる SPI_GETWORKAREA は,::GetMonitorInfo で戻されるものと同じ?

システム     0  61 1920 1080
アプリケーション 0 122 3840 2160

::GetSystemMetrics(SM_?VIRTUALSCREEN) は,-1920 0 .
::GetSystemMetrics(SM_C?VIRTUALSCREEN) は,上をずらしているので少し異なる.

システム     3840 1210
アプリケーション 5760 2160

Z170S0  ディスプレイの配置
https://learn.microsoft.com/ja-jp/windows/win32/gdi/the-virtual-screen

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

tcsncpy_s Buffer is too small

先日更新した ツール をテストしていると,フォントによりアプリケーションエラー?となってしまう.
デバッガで追いかけると,
—————————
Microsoft Visual C++ Runtime Library
—————————
Debug Assertion Failed!
Program: c:\Temp\i_Tools\TToPA\Debug.120\TToPA.exe
File: f:\dd\vctools\crt\crtw32\h\tcsncpy_s.inl
Line: 62
Expression: (L"Buffer is too small" && 0)
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)
—————————
tcsncpy_s Buffer is too small
CRichEditCtrl を使用した CHARFORMATW の szFaceName の指定がうまくなかった.
::TcsNCpy(cf.szFaceName,LF_FACESIZE-1,faceName,LF_FACESIZE-1) ;
::TcsNCpy は,幾つかの環境でビルドできる様にしたもので,今回の場合は ::tcsncpy_s と同様もの.
faceName に与えたものが L"Bahnschrift Light SemiCondensed" で,コピー先のバッファが足りないため.
正しくは,
::TcsNCpy(cf.szFaceName,LF_FACESIZE-0,faceName,LF_FACESIZE-1) ;


これらの動作は,LOGFONT の時にもよく利用する.
既存のコードを検索してみると,LF_FACESIZE を正しく指定できていた.
::TcsCpy(lf.lfFaceName,LF_FACESIZE,tstring(faceName).substr(0,LF_FACESIZE-1).c_str()) ;
与えるデータは LF_FACESIZE-1 としている.

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

GetGlyphOutline ::PolyPolygon

求めたアウトラインをウィンドウに表示できる様な変換のコードを書いたので,その動作のテスト.

{
	HWND	hWnd = ::GetConsoleHwnd() ;
	RECT	rect = ::GetClientRect(hWnd) ;
	POINT	point= ::RECT_center(rect) ;
	int  	ch   = ::RECT_width(rect)/str.length()*10/7 ;
	{
		HDC  	hDC  = ::GetDC(hWnd) ;
		{
			#define	face_A	_T("Arial")
			#define	face_U	_T("Meiryo UI")
			#define	face_W	_T("Wingdings")
			{
				::ClearWindow(hWnd) ;
				int  	ry = -30 ;
				tstring	face_name = face_U ;
				vv_PLF	vv_plf= ::GetTTOutline(hDC,point,false,str.c_str(),face_name.c_str(),ch,0,0,ry,FW_DONTCARE) ;
				v_Vd2A	v_v2a = ::ToVd2A(vv_plf) ;
				::PolyPolygon(hDC,v_v2a) ;
				}
			}
		::ReleaseDC(hWnd,hDC) ;
		}
	}

::GetTTOutline の中では,文字の傾き,文字列の回転,Y の反転,表示位置の移動を行っている.
アウトラインデータを ::PolyPolygon で描画
更に三角形に分割.

		vv_PLF	vv_plf= ::GetTTOutline(hDC,point,false,str.c_str(),face_name.c_str(),ch,0,0,ry,FW_DONTCARE) ;
	//	v_Vd2A	v_v2a = ::ToVd2A(vv_plf) ;
		v_Vd2A	v_v2a = ::PLF_triangulation(vv_plf) ;

三角形に分割


文字列 DXF 変換 Ver. 1.72

Is this 投稿 useful? Useful Useless 2 of 2 people say this 投稿 is useful.

error C2061 , C2091 , C2809 , C2556

1997/06 に作成したプロジェクトをビルドすると…

--------------------Configuration: FontFam - Win32 Release--------------------

FontFam.exe - 0 error(s), 0 warning(s)
--------------------Configuration: FontFam - Win32 Debug--------------------
Compiling...
FontFDlg.cpp
c:\program files (x86)\microsoft visual studio\vc98\include\new(35) : error C2061: syntax error : identifier 'THIS_FILE'
c:\program files (x86)\microsoft visual studio\vc98\include\new(35) : error C2091: function returns function
c:\program files (x86)\microsoft visual studio\vc98\include\new(35) : error C2809: 'operator new' has no formal parameters
c:\program files (x86)\microsoft visual studio\vc98\include\new(36) : error C2061: syntax error : identifier 'THIS_FILE'
c:\program files (x86)\microsoft visual studio\vc98\include\new(37) : error C2091: function returns function
c:\program files (x86)\microsoft visual studio\vc98\include\new(37) : error C2556: 'void *(__cdecl *__cdecl operator new(void))(unsigned int,const struct std::nothrow_t &)' : overloaded function differs only by return type from 'void *(__cdecl *__cd
ecl operator new(void))(unsigned int)'
        c:\program files (x86)\microsoft visual studio\vc98\include\new(35) : see declaration of 'new'
c:\program files (x86)\microsoft visual studio\vc98\include\new(41) : error C2061: syntax error : identifier 'THIS_FILE'
c:\program files (x86)\microsoft visual studio\vc98\include\new(42) : error C2091: function returns function
c:\program files (x86)\microsoft visual studio\vc98\include\new(42) : error C2556: 'void *(__cdecl *__cdecl operator new(void))(unsigned int,void *)' : overloaded function differs only by return type from 'void *(__cdecl *__cdecl operator new(void))
(unsigned int)'
        c:\program files (x86)\microsoft visual studio\vc98\include\new(35) : see declaration of 'new'
c:\program files (x86)\microsoft visual studio\vc98\include\new(42) : error C2809: 'operator new' has no formal parameters
c:\program files (x86)\microsoft visual studio\vc98\include\new(42) : error C2065: '_P' : undeclared identifier
Error executing cl.exe.

FontFam.exe - 11 error(s), 0 warning(s)

以前は <memory>インクルードを追加 することで対応していた.


原因は,幾つかのインクルードが次のコードより後に存在しているため?

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

今回は,インクルードしている hxx を前に持ってくることで対応.
error C2061: syntax error : identifier 'THIS_FILE' の対応

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

コンソール AP で DC の使用

ChatGPT で「Windows コンソールアプリで DC を使用する方法」と入力してみた.
ChatGPT  Windows コンソールアプリで DC を使用する方法
すると,使えそうなコードが表示された.

#include	<Windows.h>
#include	"i_define.hxx"
#include	"con_wnd.hxx"

int main() {
    // 1. コンソールウィンドウのハンドルを取得する
    HWND consoleWindow = ::GetConsoleWindow();
    // 2. コンソールウィンドウのDCを取得する
    HDC consoleDC = GetDC(consoleWindow);
    // 3. DCを使用して描画する
    TextOut(consoleDC, 10, 100, _T("Hello, World!"), _tcslen(_T("Hello, World!")));
    // 4. DCを解放する
    ReleaseDC(consoleWindow, consoleDC);
    return 0;
}

そのままではエラーになる部分があったので,少し修正している.
コンソール AP のウィンドウに TextOut (dc,...)
コンソール AP のウィンドウで GDI が使えるのは知らなかった.


BMP を表示するコード.

{
//	...
	tstring	dib_name = file_name ;
	if (::File_IsNothing(dib_name))	{	return	false ;		}
	i_DIB	dib = ::DIB_Load(dib_name.c_str()) ;
	{
		HWND	hWnd = ::GetConsoleWindow() ;
		{
			RECT	rect =	{	0	} ;
			::GetWindowRect(hWnd,&rect) ;
			HDC	hDC  = ::GetDC(hWnd) ;
			::DrawDIB(hDC,rect,dib) ;
			::ReleaseDC(hWnd,hDC) ;
			}
		}
//	...
	}

コンソール AP で BMP の表示
::AlphaBlend
更に自前のコードを利用して,サムネイルの表示.

	{
		HWND	hWnd = ::GetConsoleHwnd  () ;
		D_I_E	die ;
		die.SetDocPath(dib_name.c_str()) ;
		die.Draw(hWnd) ;
		}
Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

error C2678: 二項演算子 ‘=’ :

ある処理を関数にしてコンパイルすると,

--------------------構成: VFDiv_1 - Win32 Debug--------------------
コンパイル中...
VFDiv_1V.cpp
c:\program files (x86)\microsoft visual studio\vc98\include\algorithm(232) : error C2678: 二項演算子 '=' : 型 'const struct Vector2<double>' の左オペランドを扱う演算子は定義されていません。(または変換できません)(新しい動作; ヘルプを参照)
        c:\program files (x86)\microsoft visual studio\vc98\include\algorithm(228) : コンパイルされたクラスのテンプレートのインスタンス化 'void __cdecl std::_Iter_swap(const struct Vector2<double> *,const struct Vector2<double> *,struct Vector2<double> *)' の参照を確認してください
c:\program files (x86)\microsoft visual studio\vc98\include\algorithm(232) : error C2678: 二項演算子 '=' : 型 'const struct Vector2<double>' の左オペランドを扱う演算子は定義されていません。(または変換できません)(新しい動作; ヘルプを参照)
        c:\program files (x86)\microsoft visual studio\vc98\include\algorithm(228) : コンパイルされたクラスのテンプレートのインスタンス化 'void __cdecl std::_Iter_swap(const struct Vector2<double> *,const struct Vector2<double> *,struct Vector2<double> *)' の参照を確認してください
cl.exe の実行エラー

VFDiv_1.exe - エラー 2、警告 0

対象が ‘const struct Vector2<double>’ となっているので,わかり辛かった.
次の関数の,’const Vd2A& v2a’ を std::reverse(v2a.begin(),v2a.end()) として使用しているのが原因.

PLF_face_l	PLF_triangulation	(const Vd2A& v2a)
{
//	...
	std::reverse(v2a.begin(),v2a.end()) ;
//	...
	}

一度関数内の変数に置く必要がある.
error C2678

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

VirusTotal Cylance Unsafe

1 年位前から,exe をビルドしてデバッグが終わると VirusTotal でチェックしている.
それで,誤検知されやすいと思われる VC のバージョンなどのメモ.


VC6.exe では,ほとんどが何らかのものに引っ掛かってしまう.
SecureAge Malicious
VC8.exe や VC9.exe も何かに引っ掛かってしまうことが多い.
VC 10 ~ VC 12 では,あまり規則性はわからない.コードによる?


VC 14 以降は,普通の MFC のコードであればほぼ問題なさそう.
但し最初のうちは,ほとんど Cylance Unsafe となってしまう.
VirusTotal Cylance Unsafe
が,数日経過すると警告は消えることが多い.

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

error C2668: ‘abs’

1>------ ビルド開始: プロジェクト: ClCpy, 構成: Debug Win32 ------
1>コンパイルしています...
1>ClCpyDlg.cpp
1>l:\document\develop\tools\_free\tiny\clcpy\clcpydlg.cpp(396) : error C2668: 'abs' : オーバーロード関数の呼び出しを解決することができません。(新機能 ; ヘルプを参照)
1>        c:\program files (x86)\microsoft visual studio 8\vc\include\math.h(539): 'long double abs(long double)' の可能性があります。
1>        c:\program files (x86)\microsoft visual studio 8\vc\include\math.h(491): または 'float abs(float)'
1>        c:\program files (x86)\microsoft visual studio 8\vc\include\math.h(487): または 'double abs(double)'
1>        c:\program files (x86)\microsoft visual studio 8\vc\include\math.h(485): または 'long abs(long)'
1>        c:\program files (x86)\microsoft visual studio 8\vc\include\stdlib.h(415): または 'int abs(int)'
1>        引数リスト '(size_t)' を一致させようとしているとき
1>ビルド時間 0:07
1>ClCpy - エラー 1、警告 0
========== ビルド: 0 正常終了、1 失敗、0 更新、0 スキップ ==========

error C2668: 'abs' : オーバーロード関数の呼び出しを解決することができません。
次の様に long にキャストすることで対応.
size_t len_ = ::abs(long(lenS-lenD)) ;

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

Win11 MFC80u.dll などの場所

VC 2005 で作成した exe がうまく起動しないと連絡が入った.
すぐに dll などがないためとわかり,VC 2005 SP1 vcredist_x86.exe を入れて対応してもらった.
https://jml.mish.work/index.php/cpp/ref-vcredist-xxx-exe.html


それで,Win11 環境の c:\Windows\WinSxS\ の MFC80*.dll を見ると,それらしいものが見当たらない.
Win10 では …\WinSxS\ に存在する.
Win10 WinSxS x86 vc80 mfc
explorer で検索すると Win11 では ..\WinSxS\Fusion\ 以下になっている.
Win11 WinSxS\Fusion\ x86 vc80 mfc


WinSxS 以下のサイズ.
Win10 WinSxS
Win11 WinSxS


Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

.NET ZipFile C++/CLI

ZipFile クラスのサンプル を C++/CLI で.
Win32 コンソール AP としてプロジェクトを作成.
CPP を次の様に変更.

#include	<stdio.h>
#include	<tchar.h>

//	using	System;
//	using	System.IO.Compression;
#using  	<System.dll>
#using		<System.IO.Compression.FileSystem.dll>

//	class Program
//	{
//		static void Main(string[] args)
//		{

int _tmain(int argc, _TCHAR* argv[])
{
//			string  startPath	= @"./start";
//			string  zipPath  	= @"./result.zip";
//			string  extractPath	= @"./extract";
		System::String^	startPath	= _T("./start") ;
		System::String^	zipPath  	= _T("./result.zip") ;
		System::String^	extractPath	= _T("./extract") ;

//		                         ZipFile. CreateFromDirectory(startPath, zipPath);
		System::IO::Compression::ZipFile::CreateFromDirectory(startPath, zipPath);

//		                         ZipFile. ExtractToDirectory(zipPath, extractPath);
		System::IO::Compression::ZipFile::ExtractToDirectory(zipPath, extractPath);

	return 0;
	}

//			}
//		}

そのままビルドすると…

1>------ ビルド開始: プロジェクト: T_ZIP_C, 構成: Debug Win32 ------
1>  T_ZIP_C.cpp
1>d:\document\vs\vs\2012\t_clr\t_zip_c\t_zip_c.cpp(6): fatal error C1190: マネージ ターゲット コードには '/clr' が必要です。
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========

fatal error C1190: マネージ ターゲット コードには '/clr' が必要です。
プロジェクトの設定で「/clr」に.

1>------ ビルド開始: プロジェクト: T_ZIP_C, 構成: Debug Win32 ------
1>  T_ZIP_C.cpp
1>T_ZIP_C.cpp(7): fatal error C1107: アセンブリ 'System.IO.Compression.FileSystem.dll' がみつかりませんでした: /AI または LIBPATH 環境変数を使用してアセンブリ検索パスを指定してください。
========== ビルド: 0 正常終了、1 失敗、3 更新不要、0 スキップ ==========

「追加の #using ディレクトリ」に dll の場所を指定して通る様にはなったが,これで良いかがわからない.
fatal error C1107: アセンブリ 'System.IO.Compression.FileSystem.dll' がみつかりませんでした:


ほとんど何も入っていない環境で実行すると,

---------------------------
T_ZIP_C.exe - システム エラー
---------------------------
MSVCR110.dll が見つからないため、コードの実行を続行できません。プログラムを再インストールすると、この問題が解決する可能性があります。 
---------------------------
OK   
---------------------------

MSVCR110.dll が見つからないため、コードの実行を続行できません。
VC 2013 や 2015 でビルドしたものも試してみたが,この環境では実行できなかった.
対応するものを入れる必要があるのか?
https://jml.mish.work/index.php/cpp/ref-vcredist-xxx-exe.html


zip_CLI.hxx

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

簡易 Web サーバ C++/CLI

先日の C# のコードから C++/CLI に書き直したものの 更新版
index.html の作成と,ContentType の設定,日本語ファイル名への対応など.

#ifdef		__cplusplus_cli
#using		<System.dll>
#using		<System.Web.dll>
#include	<vcclr.h>
#endif

///////////////////////////////////////////////////////////////////////////
#include	"S_Exec.hxx"
#include	"str_CLI.hxx"
#include	"filestat.hxx"
#include	"filepath.hxx"
#include	"ask_path.hxx"
#include	"itls_tmp.hxx"
#include	"textfile.hxx"
#include	"htmout.hxx"
#include	"stringfn.hxx"

///////////////////////////////////////////////////////////////////////////
struct	MIME_type	{
		LPCTSTR	FExt ;
		LPCTSTR	Type ;
		} ;

//	https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
const	MIME_type	MIME_type_tbl[] =
		{
			_T("htm" ) ,	_T("text/html") ,
			_T("html") ,	_T("text/html") ,
			_T("txt" ) ,	_T("text/plain") ,
			_T("bmp" ) ,	_T("image/bmp") ,
			_T("jpeg") ,	_T("image/jpeg") ,
			_T("jpg" ) ,	_T("image/jpeg") ,
			_T("png" ) ,	_T("image/png") ,
			_T("svg" ) ,	_T("image/svg+xml") ,
			_T("bin" ) ,	_T("application/octet-stream") ,
			_T("pdf" ) ,	_T("application/pdf") ,
			_T("zip" ) ,	_T("application/zip") ,
			_T("   " ) ,	_T("") ,
			_T("\0"  ) ,	_T("") ,
			_T(""    ) ,	_T("") ,
		} ;

inline	tstring	get_MIME_type	(LPCTSTR ext_)
{
	tstring	type = _T("application/octet-stream") ;
	tstring	ext  = ::String_ToLower(ext_) ;
	if (ext.empty())	{
		return	type ;
		}
	const	MIME_type*	mm_ty = MIME_type_tbl ;
	{
		for (size_t index=0 ; index<countof(MIME_type_tbl) ; index++)
		{
			tstring	fext = mm_ty[index].FExt ;
			tstring	ftyp = mm_ty[index].Type ;
			if (fext.length() == 0)          	{	continue ;	}
			if (fext.length() != ext.length())	{	continue ;	}
			if (ext == fext)                	{
				return	mm_ty[index].Type ;
				}
			}
		}
	return	type ;
	}

///////////////////////////////////////////////////////////////////////////
inline	tstring	HT_Make_index_content	(c_tstring& fold)
{
	v_tstring	sub_folds = ::EnumFolders(fold.c_str()) ;
	v_tstring	htm_files = ::EnumFiles  (fold.c_str(),_T("*.htm*")) ;
	tstring		foldName  = ::Path_GetTitle(fold) ;
	tstring	htm_str ;
	{
		Xml_E	htm = HtmOut::html() ;
		{
			Xml_E	head(HTM_head) ;
			{
				head.AddChild(HtmOut::charset_UTF_8()) ;
				head.AddChild(HtmOut::meta_viewport()) ;
				head.AddChild(HtmOut::title(foldName)) ;
				}
			{
				head.AddChild(HtmOut::comment()) ;
				}
			htm.AddChild(head) ;
			}
		{
			Xml_E	body(HTM_body) ;
			{
				{
					body.AddChild(HtmOut::a_parent()) ;
					body.AddChild(HtmOut::hr()) ;
					}
				{
					for (size_t index=0 ; index<sub_folds.size() ; index++) {
						tstring	fold = sub_folds[index] ;
						       	fold = ::Path_DelLastSP(fold) ;
						Xml_E	a_fold = HtmOut::a(::Path_GetName(fold)+_T("/")) ;
						body.AddChild(a_fold) ;
						body.AddChild(HtmOut::br()) ;
						}
					body.AddChild(HtmOut::hr()) ;
					}
				{
					for (size_t index=0 ; index<htm_files.size() ; index++) {
						tstring	html = htm_files[index] ;
						Xml_E	a_html = HtmOut::a(::Path_GetName(html)) ;
						body.AddChild(a_html) ;
						body.AddChild(HtmOut::br()) ;
						}
					}
				}
			htm.AddChild(body) ;
			}
		htm_str = htm.ToText() ;
		}
	return	htm_str ;
	}

tstring		Make_index	(c_tstring& fold)
{
	tstring	result = ::HT_Make_index_content(fold) ;
	return	result ;
	}

///////////////////////////////////////////////////////////////////////////
bool	web_server	(c_tstring& fold,const u_16 port)
{
	tstring	root_ = fold ;
	tstring	port_ = ::To_tstring(port) ;
	tstring	pref_ = _T("http://127.0.0.1:")+port_+_T("/") ;
	System::String^	root	= ::to_gcString(root_) ;
	System::String^	prefix	= ::to_gcString(pref_) ;
	System::Console::WriteLine(prefix) ;
	System::Net::HttpListener^	listener = gcnew System::Net::HttpListener();
	listener->Prefixes->Add(prefix);
	listener->Start();
	while (true) {
		System::Net::HttpListenerContext^	context = listener->GetContext();
		System::Net::HttpListenerRequest^	req = context->Request;
		System::Net::HttpListenerResponse^	res = context->Response;
		System::String^	path = root + req->RawUrl->Replace("/", "\\");
		             	path = System::Web::HttpUtility::UrlDecode(path) ;
		{
			System::Console::WriteLine(req->RawUrl);
			System::Console::WriteLine(path) ;
			}
		if (System::IO::File::Exists(path)) {
			}
		if (System::IO::File::Exists(path)) {
			tstring	ext = ::Path_GetExtLow(::to_tstring(path)) ;
			array<System::Byte>^	content = System::IO::File::ReadAllBytes(path);
			res->ContentType = ::to_gcString(::get_MIME_type(ext.c_str())) ;
			res->OutputStream->Write(content, 0, content->Length);
			}
		else {
			tstring               	cnt_index = ::Make_index (::to_tstring(path)) ;
			array<System::Byte>^	content ;
			{
				static	long	i_count = 0 ;
				            	i_count++ ;
				tstring	tmp_path = ::Get_i_Tools_tmp_date() ;
				tstring	htm_name = ::To_tstring(port) + _T("_") + ::u32to0t(i_count,10,4) + _T(".htm") ;
				tstring	out_path = ::Path_AddLastSP(tmp_path) + htm_name ;
				::SaveUTF8(out_path.c_str(),cnt_index) ;
				content = System::IO::File::ReadAllBytes(::to_gcString(out_path.c_str())) ;
				}
			res->ContentType = ::to_gcString(::get_MIME_type(_T("htm"))) ;
			res->OutputStream->Write(content, 0, content->Length);
			}
		res->Close();
		}
	return	true ;
	}

///////////////////////////////////////////////////////////////////////////
bool	test	(c_tstring& str)
{
	tstring	fold = str ;
	{
		if (::File_IsDirectory(fold))	{	;                          	}
		else                        	{	fold = ::Path_GetDir(fold) ;	}
		}
	std::terr << fold << std::endl ;
	{
		u_16	tick = u_16(::GetTickCount()) ;
		u_16	port = u_16(50000 + (tick&0x1fff)) ;
		{
			tstring	port_ = ::To_tstring(port) ;
			tstring	pref_ = _T("http://127.0.0.1:")+port_+_T("/") ;
			S_Exec	se ;
			se.SetFile(pref_.c_str()) ;
			se.Execute() ;
			}
		::web_server(fold,port) ;
		}
	return	true ;
	}

///////////////////////////////////////////////////////////////////////////
int	_tmain	(int argc,_TCHAR* argv[])
{
	tstring	path ;
	{
		#ifdef	OFN_filter_All
			path = ::ask_path(false) ;
		//	path = ::ask_path(true) ;
		#else
			path = ::ask_cli(_T("folder ... ? =")) ;
		#endif
		}
	if (!path.empty()) {
		::test(path) ;
		}
	return 0;
	}

///////////////////////////////////////////////////////////////////////////
#include	"messbar.cxx"

* 幾つかのコードが揃っていないため,そのままではビルドできません.
簡易 Web サーバ   C++/CLI
https://jml.mish.work/index.php/i-tools/web-svr.html

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

C# のコードを C++/CLI に

先日の「簡易 Web サーバ C#」のコードを C++ で.

///////////////////////////////////////////////////////////////////////////////////
//	C# -> C++/CLI
///////////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <tchar.h>

//using	System;
//using	System.IO;
//using	System.Net;

#using  <System.dll>

bool	test	(void)
{
//
//	class SimpleWebServer
//	{
//		static void Main()
//		{
//			string		root = @"c:\wwwroot\";	// ドキュメント・ルート
//					root = @".\";
			System::String^	root = "./" ;
//			string		prefix = "http://*/";	// 受け付けるURL
//					prefix = "http://127.0.0.1:65432/" ;
			System::String^	prefix = "http://127.0.0.1:55555/" ;
//	
//			HttpListener 			listener = new HttpListener();
			System::Net::HttpListener^	listener = gcnew System::Net::HttpListener();
//			listener. Prefixes. Add(prefix);	// プレフィックスの登録
			listener->Prefixes->Add(prefix);
//			listener. Start();
			listener->Start();
//	
//			while (true) {
			while (true) {
//				HttpListenerContext			context = listener. GetContext();
				System::Net::HttpListenerContext^	context = listener->GetContext();
//				HttpListenerRequest			req = context. Request;
				System::Net::HttpListenerRequest^	req = context->Request;
//				HttpListenerResponse			res = context. Response;
				System::Net::HttpListenerResponse^	res = context->Response;
//	
//				Console.	 WriteLine(req. RawUrl);
				System::Console::WriteLine(req->RawUrl);
//	
//				// リクエストされたURLからファイルのパスを求める
//				string		path = root + req. RawUrl. Replace("/", "\\");
				System::String^	path = root + req->RawUrl->Replace("/", "\\");
//	
//				// ファイルが存在すればレスポンス・ストリームに書き出す
//				if (            File. Exists(path)) {
				if (System::IO::File::Exists(path)) {
//					byte[]			content =             File. ReadAllBytes(path);
					array<System::Byte>^	content = System::IO::File::ReadAllBytes(path);
//					res. OutputStream. Write(content, 0, content. Length);
					res->OutputStream->Write(content, 0, content->Length);
//					}
					}
//				res. Close();
				res->Close();
//				}
				}
//			}
//		}
//
	return	true ;
	}

int _tmain(int argc, _TCHAR* argv[])
{
	::test() ;
	return 0;
	}

Web サーバ   C++/CLI

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

VC 8 で C++/CLI

VC 10 ではある程度確認が取れたので,今度は VC 8 で.
先ず,コンソール AP .ビルドすると,

1>------ ビルド開始: プロジェクト: T_Con_1, 構成: Debug Win32 ------
1>コンパイルしています...
1>T_Con_1.cpp
1>EnumFile.hxx MessageBar  No Support
1>C:\Program Files (x86)\Microsoft Visual Studio 8\VC\include\vcclr.h(43) : error C2446: '!=' : 'int' 型から 'cli::interior_ptr<Type>' 型への変換ができません。
1>        with
1>        [
1>            Type=unsigned char
1>        ]
1>T:\Develop\_.SRC\_CLI\str_CLI.hxx(41) : error C2446: '==' : 'int' 型から 'System::String ^' 型への変換ができません。
1>        使用可能なユーザー定義された変換演算子がない、または
1>        演算型のボックス化された形式からターゲット型への標準変換は存在しません
1>T:\Develop\_.SRC\_CLI\str_CLI.hxx(61) : warning C4267: '初期化中' : 'size_t' から 'int' に変換しました。データが失われているかもしれません。
1>T:\Develop\_.SRC\_CLI\str_CLI.hxx(64) : warning C4267: '初期化中' : 'size_t' から 'int' に変換しました。データが失われているかもしれません。
1>T_Con_1 - エラー 2、警告 2
========== ビルド: 0 正常終了、1 失敗、0 更新、0 スキップ ==========

vcclr.h 内のエラーは,次の様に cpp の最初で vcclr.h を読み込むことで回避できる.

#ifdef      __cplusplus_cli
#include    <vcclr.h>
#endif

もう一つのエラーは次の所で,str が nullptr でないかを比較している所.

tstring	to_tstring	(System::String^ str)	
{
	if (str == nullptr)		{	return	_T("") ;	}
	pin_ptr	<const wchar_t>	pStr = PtrToStringChars(str) ;
	tstring	tstr = pStr ;
	return	tstr ;
	}

検索すると System::String::Empty を使えば良さそうたが,str が 0 との比較は必要ないのか?
VC 8 で  C++/CLI

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

fatal error C1010

昨日から VC6 で開いたままだったプロジェクトをビルドすると,あまり見慣れないエラーが…

--------------------Configuration: AsTrmM - Win32 Debug--------------------
Compiling...
HProRNew.cpp
t:\develop\_.src\...\hprornew.cpp(113) : fatal error C1010: unexpected end of file while looking for precompiled header directive
Error executing cl.exe.

AsTrmM.exe - 1 error(s), 0 warning(s)

他の環境で試そうとプロジェクトを閉じようとすると,保存するかの問合せが入った.
保存された dsp と先日バックアップしたそれと比べると,不要な cpp が追加されていた.
C1010  不要な cpp が追加された dsp
ソースを開いた時,操作ミスで間違ってビルド対象に cpp が追加されてしまったみたい.
不要な cpp をプロジェクトから外して対応.うまくいった.


私の場合,自動生成される以外のソースは,次の様な複数の cpp をプロジェクトに追加して運用しています.

ComUse01.cpp
	#include    "StdAfx.h"
	#include    "ComPrj00.hpp"

	#include    "Point.cxx"
	#include    "Matrix.cxx"
	//          ...
ComPrj00.hpp
	#include    "i3DV.h"           // App.h
	#include    "ColorHSV.hxx"
	//          ...


Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

高 DPI ペンの幅

引き続きやっているが,なかなか難しい.
左は「非対応.exe」を「プロパティ」で「アプリケーション」にしたもの.
LOGPEN 100% 200%
0.2 mm の指定で印刷する場合は問題ないが,27 インチ 4K では 1 ピクセルになり非常に見辛い.


今度は,VC 12 以降で「モニターごとの高い DPI 認識」としたもの.
LOGPEN Win7 , 8.1
Win7 では「非対応.exe」でも「アプリケーション」と指定したものの様な動作?
8.1 以降は,「DPI 認識」で指定したものが効いている?
VC 12 以降 「マニフェスト ツール」-「DPI 認識」


4K 環境の Win10 で「非対応.exe」.
VC 6 exe 96 DPI
exe のプロパティで「システム(拡張)」としたもの.
VC 6 exe 192 DPI
0.3 mm の線を表示すると「システム(拡張)」としたものの方がきれい.


AP の作り方にもよると思うが,exe のプロパティで「システム(拡張)」としたものが一番良さそう.
「アプリケーション」にしてしまうと?,他のモニタに移動した時に大きさなどがうまくない.

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

::GetDpiForWindow

高 DPI 関連でいろいろと調べてみると ::GetDpiForWindow を使う必要がありそう.
ただ使えるのが Win10 1607 以降みたいで,その辺りをどうしたものか?


次の様に呼出せば 指定した hwnd の値が取れることは確認

	#if	(_MSC_VER >= 1900)
	{
		UINT	dpi = ::GetDpiForWindow(hwnd) ;
		std::terr << dpi << std::endl ;
		}
	#endif

ただ,旧 Windows では存在しないため実行時エラーになる.
そのため ::GetProcAddress利用した方法に

//	UINT	GetDpiForWindow ( [in] HWND hwnd ) ;
typedef	UINT	(WINAPI* P_GDFW)(HWND) ;

UINT	GetDPI	(HWND hwnd)
{
	UINT	dpi = 96/2 ;
	HMODULE	user32 = ::GetModuleHandle(TEXT("user32.dll")) ;
	P_GDFW	p_GetDpiForWindow = (P_GDFW)::GetProcAddress(user32,"GetDpiForWindow") ;
	if (p_GetDpiForWindow != NULL) {
		dpi = p_GetDpiForWindow(hwnd) ;
		}
	else {
		HDC	hdc = ::GetDC(hwnd) ;
		dpi = ::GetDeviceCaps(hdc,LOGPIXELSX) ;
		::ReleaseDC(hwnd,hdc) ;
		}
	return	dpi ;
	}

Win11 で「拡大/縮小」の値を変更したもの.
作成した ::GetDPI を利用した VC6  exe


解像度と DPI の関係が,まだうまく理解できていない.
::GetDpiForWindow は,指定した hwnd の DPI が取得できている.
::GetDeviceCaps では,プライマリの情報が取れる.
「非対応」の場合はスケーリングされた値,「モニターごと」の場合は 100% での値?

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

buf = string ( buf.c_str () )

先日の共通のコードでのバグ.

tstring	ask_cli	(LPCTSTR msg=_T(""))
{
	tstring	cli ;
	while(true)	{
		tstring	buf ;
		buf.resize(1000) ;
		std::terr << msg ;
		std::tin.getline(&buf[0],std::streamsize(buf.size())) ;
	//	buf = ::QuotM_Del_All(buf.c_str()) ;
		if      (buf == _T("q"))	{	break ;		}
		else if (buf == _T("Q"))	{	break ;		}
		if (buf.empty())         	{	continue ;	}
		cli = buf.c_str() ;
		break ;
		}
	return	cli ;
	}

ループを抜けるために “q” や “Q” と比較している部分が機能しない(break しない).
原因は “q\0\0\0…” と “q\0” を比べているため.
そのため,比較する前に次の様にするとうまく機能する.

{
	tstring	tmp = buf.c_str() ;
	buf = tmp ;
	}

MFC であれば CString::ReleaseBuffer(-1) が使えるが…
buf = tstring(buf.c_str()) とすることで対応.
buf = string ( buf.c_str() )


CString , std::string , …

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.