TIPS、メモ

外部からマクロを実行する

> 質問1:
> 外部プログラムからマクロ(プロシージャ指定、1行指定どちらでも
> かまわないのですが)をQXに実行させることは出来ないでしょうか?

#include <windows.h>
#define WM_USEREXECMACRO	(WM_USER+2010)
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	 LPSTR lpszCmdLine, int nCmdShow)
{
	COPYDATASTRUCT cds;
	HWND hwnd;
	char *p = "z.mac";

	hwnd = FindWindow("QXWclassframe32", NULL);
	if (hwnd==(HWND)0) return(0);
	cds.dwData = WM_USEREXECMACRO;
	cds.cbData = p!=NULL ? strlen(p)+1:0;
	cds.lpData = p;
	SendMessage(hwnd, WM_COPYDATA, (WPARAM)0, (LPARAM)&cds);
	return(0);
}

ファイルの有無を調べるAPI


dllname "SHLWAPI.DLL"
cdeclare long PathFileExists(LPCSTR)

PathFileExistsの引数にファイルのフルパスを渡せば,ファイルがある場合には0以外が返る。

(例)ディレクトリの中から "XXX.html" という数字の名前でまだ作られていない一番小さいファイルを開く


	dim num
	dim dirpath$
	dim path$
	
	dirpath$ = "c:\Documents\"
	num = 1
	do		'まだ作られていないファイルを探す
		num++
		path$ = dirpath$ & cformat$("%03d.html", num)
	loop while PathFileExists(path$)
	if(@@OpenFile(path$) = 0) then exit proc

開くダイアログでショートカットを有効にする

レジストリやINIファイルのQXMODE3の値に1を設定する。

日時用のAPIを使う

ほかにも方法はありますがAPIから日付を取ってくるにはこんな感じ。


Type SYSTEMTIME
      wYear          As Integer
      wMonth         As Integer
      wDayOfWeek     As Integer
      wDay           As Integer
      wHour          As Integer
      wMinute        As Integer
      wSecond        As Integer
      wMilliseconds  As Integer
End Type

Type FILETIME
  dwLowDateTime As Long
  dwHighDateTime As Long
End Type

dllname KERNEL
cdeclare void GetLocalTime(SYSTEMTIME *);
cdeclare void GetSystemTime(SYSTEMTIME *);
cdeclare long SystemTimeToFileTime(SYSTEMTIME *, FILETIME *);
cdeclare long FileTimeToSystemTime(FILETIME *, SYSTEMTIME *);
cdeclare long CompareFileTime(FILETIME *, FILETIME *);

proc main
	dim st as SYSTEMTIME
	dim ft as FILETIME
	GetLocalTime(st)
	SystemTimeToFileTime(st, ft)
	'FILETIME は100ナノ間隔の構造体
	'int64に入れなおして計算する
	'QXで64ビット整数の計算はそれなりに手間がかかると思う。
'   #define _MICROSECOND ((__int64)10)
'   #define _MILLISECOND (1000 * _MICROSECOND)
'   #define _SECOND (1000 * _MILLISECOND)
'   #define _SECOND ((__int64) 10000000)
'   #define _MINUTE (60 * _SECOND)
'   #define _HOUR   (60 * _MINUTE)
'   #define _DAY    (24 * _HOUR)
	
end proc

GetLocalTimeがあればことは足りると思うけど,時間を引いたり足したりする場合にはFILETIME構造体に入れなおしてから計算する必要があります。SystemTimeToFileTimeでFILETIMEに変換してから,時間を足したり引いたりして,FileTimeToSystemTimeで元に戻します。

コメントにも書いてありますが,マクロで64ビット整数を計算するのはそれなりに面倒だと思います。64ビット整数計算用のdllがネット上にありますので,そちらを使った方が楽でしょう。私が作ったのもあります(こちら)。

CryptGenRandom

(2015年3月4日)XP 以降に追加された乱数生成APIを呼び出すマクロ。


' CryptGenRandom マクロ

dllname "Advapi32.dll"
cdeclare long CryptAcquireContext(long *, LPCSTR, LPCSTR, long, long);
cdeclare long CryptGenRandom(long, long, long *);
cdeclare long CryptReleaseContext(long, long);

proc main
	dim hProv as long
	dim rand as long
	dim ret as long
	dim PROV_RSA_FULL as long
	PROV_RSA_FULL = 1

	ret = CryptAcquireContext(hProv, 0, 0, PROV_RSA_FULL, 0)
	ret = CryptGenRandom(hProv, 4, rand)
	ret = CryptReleaseContext(hProv, 0)

	call msgbox(cformat$("%d", rand))
end proc

' CryptGenRandom は実際には任意の BYTE 配列の中に乱数を埋める API ですが、ここでは 32bit 整数に埋めさせています。