unit general; //{$DEFINE DEBUG} interface uses Classes, Clipbrd, Windows, Graphics, //Windowsの後にしないとだめ SysUtils; //myWindow.pas function gfnptMousePosGet: TPoint; function gfnptClientMousePosGet(hHandle: HWND): TPoint; function gfnbKeyState(iKey: Integer): Boolean; function gfnsClassNameGet(hHandle: HWND): String; function gfnsWindowTextGet(hHandle: HWND): WideString; function gfnhWindowGet(APoint : TPoint): HWND;// overload; function gfnhParentWindowGet(hHandle: HWND): HWND; function gfnsExeNameGet(hHandle: HWND): WideString; overload; function gfnrcWindowRectGet(hHandle: HWND): TRect; function gfnrcClientRectGet(hHandle: HWND): TRect; function gfnptScreenToClient(hHandle: HWND; ptPos: TPoint): TPoint; //function gfnbIsNtOs: Boolean; function gfnsOsNameGet: WideString; function gfnbIsOSUpper2000: Boolean; //myNum.pas function gfniStrToInt(sNum: String): Int64; function gfniRound(fNum: Extended): Int64; function gfniRoundUp(fNum: Extended): Int64; function gfniNumLimit(iNum: Integer; iMin, iMax: Integer): Integer; function gfniNumLoop(iNum: Integer; iMin, iMax: Integer): Integer; function gfniMax(iNum: array of Integer): Integer; //mySize.pas function gfniRectWidth (rtRect: TRect): Integer; function gfniRectHeight(rtRect: TRect): Integer; function gfnrcRectCenter(rcParent, rcChild: TRect): TRect; function gfnrcRectShift (rcRect: TRect; ptShift: TPoint): TRect; overload; function gfnbCompleteRectInRect(rcCheck, rcRect: TRect): Boolean; function gfnbRectInRect(rcCheck, rcRect: TRect): Boolean; function gfnsCompasGet(ptStart, ptPos: TPoint): String; //myFile.pas function gfnsWorkFileNameGet(sExt : WideString) : WideString; function gfnsFileNameGet (sFile : WideString) : WideString; function gfnsFileExtChange (sFile, sExt : WideString) : WideString; function gfnsExeNameGet : WideString; overload; function gfnbFileExists (sFile : WideString) : Boolean; function gfniFileSizeGet (hHandle : THandle) : Int64; function gfnsFileVersionGet (sFile : WideString) : WideString; overload; function gfnsProductNameGet (sFile : WideString) : WideString; overload; function gfnsFileVersionGet : WideString; overload; function gfnsProductNameGet : WideString; overload; procedure gpcFileWriteText(sFile, sText : WideString); procedure gpcExecute (sFile : WideString); //myGraphic.pas type TMyBitmap = class(TBitmap) public procedure SaveToFile(const Filename: WideString); reintroduce; end; function gfnclColorRevers(clColor: TColor): TColor; procedure gpcColorRGBToHLS(iRed, iGreen, iBlue: BYTE; var iHue, iLuminance, iSaturation: WORD; iMaxHue, iMaxLuminance, iMaxSaturation: WORD); overload; procedure gpcColorRGBToHLS(iRed, iGreen, iBlue: BYTE; var iHue, iLuminance, iSaturation: WORD); overload; procedure gpcColorRGBToHSV(iRed, iGreen, iBlue: BYTE; var iHue, iValue, iSaturation: WORD; iMaxHue, iMaxValue, iMaxSaturation: WORD); //myClipbrd.pas procedure gpcStrToClipboard(sStr: String); //myList.pas function gfnbIsIncludeList(sValue: String; slList: TStrings): Boolean; overload; function gfnbIsIncludeList(sValue: String; slList: array of String): Boolean; overload; //myMessageBox function gfniMessageBoxYesNo(const sMsg, sTitle: String): Integer; procedure gpcShowMessage(sMsg, sTitle: String); //myString.pas function gfnbIsUnicode(sSrc: WideString): Boolean; function gfnsWideToUtf7(sSrc: WideString): AnsiString; //function gfnsUtf7ToWide(sSrc: AnsiString): WideString; function gfnsWideToUtf8(sSrc: WideString): Utf8String; function gfnsUtf8ToWide(sSrc: Utf8String): WideString; function gfnsWideToAnsi(sSrc: WideString): AnsiString; var G_bIsNtOs: Boolean = False; //============================================================================== implementation uses {$IFDEF DEBUG} myDebug, {$ENDIF} Forms, GraphUtil, Messages, PsAPI, RTLConsts, ShellAPI; //myWindow.pas ----------------------------------------------------------------- function gfnbIsNtOs: Boolean; //OSがNT系ならTrueを返す var lr_Info: TOSVersionInfo; begin Result := False; FillChar(lr_Info, SizeOf(lr_Info), 0); lr_Info.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);; if (GetVersionEx(lr_Info)) then begin Result := (lr_Info.dwPlatformId = VER_PLATFORM_WIN32_NT); end; end; function gfnptMousePosGet: TPoint; //マウスカーソルの位置をスクリーン座標で返す begin Result := Point(0, 0); GetCursorPos(Result); end; function gfnptClientMousePosGet(hHandle: HWND): TPoint; {2008-12-04: 現在のマウスカーソルの位置をウィンドウのクライアント座標で返す。 } begin Result := gfnptMousePosGet; Windows.ScreenToClient(hHandle, Result); end; function gfnbKeyState(iKey: Integer): Boolean; var li_Check: SHORT; begin //左右ボタンを入れ替えている場合に対処 if (GetSystemMetrics(SM_SWAPBUTTON) <> 0) then begin if (iKey = VK_LBUTTON) then begin iKey := VK_RBUTTON; end else if (iKey = VK_RBUTTON) then begin //2009-02-04:VK_RUBTTONとしたままだったのを修正。 iKey := VK_LBUTTON; end; end; li_Check := GetAsyncKeyState(iKey); //Result := BOOL(Hi(li_Check)) and (BOOL(Lo(li_Check))); Result := BOOL(Hi(li_Check)); end; function gfnsClassNameGet(hHandle: HWND): String; //ウィンドウハンドルhHandleのクラス名を返す const lci_LEN = 256; var lp_Buff: PChar; begin Result := ''; lp_Buff:= AllocMem(lci_LEN +1); try GetClassName(hHandle, lp_Buff, lci_LEN -1); Result := String(lp_Buff); finally FreeMem(lp_Buff); end; end; function gfnsWindowTextGetW(hHandle: HWND): WideString; const lci_MAXTEXTLEN = 256; var li_Len: DWORD; lp_Text: PWideChar; begin Result := ''; li_Len := GetWindowTextLengthW(hHandle) +1; if (li_Len > 0) then begin if (li_Len > lci_MAXTEXTLEN) then begin li_Len := lci_MAXTEXTLEN; end; lp_Text := AllocMem((li_Len +1) * 2); try GetWindowTextW(hHandle, lp_Text, li_Len); Result := WideString(lp_Text); finally FreeMem(lp_Text); end; end; if (Result <> '') then begin Exit; end; if (SendMessageTimeoutW(hHandle, WM_GETTEXTLENGTH, 0, 0, SMTO_ABORTIFHUNG, 500, li_Len) <> 0) then begin if (li_Len > 0) then begin li_Len := li_Len +1; if (li_Len > lci_MAXTEXTLEN) then begin li_Len := lci_MAXTEXTLEN; end; lp_Text := AllocMem((li_Len +1) * 2); try SendMessageTimeoutW(hHandle, WM_GETTEXT, WPARAM(li_Len), LPARAM(lp_Text), SMTO_ABORTIFHUNG, 500, li_Len); Result := WideString(lp_Text); finally FreeMem(lp_Text); end; end; end; end; function gfnsWindowTextGet(hHandle: HWND): WideString; //ウィンドウハンドルhHandleのテキスト(キャプション)を返す const lci_MAXTEXTLEN = 256; var li_Len: Integer; lp_Buff: PChar; begin Result := ''; if (G_bIsNtOs) then begin Result := gfnsWindowTextGetW(hHandle); end else begin li_Len := GetWindowTextLength(hHandle) +1; if (li_Len > 0) then begin if (li_Len > lci_MAXTEXTLEN) then begin li_Len := lci_MAXTEXTLEN; end; lp_Buff := AllocMem(li_Len +1); try GetWindowText(hHandle, lp_Buff, li_Len); Result := WideString(String(lp_Buff)); finally FreeMem(lp_Buff); end; end; end; end; function gfnptScreenToClient(hHandle: HWND; ptPos: TPoint): TPoint; {2009-03-08: ptPosをhHandleのウィンドウのクライアント座標で返す。 } begin Result := ptPos; ScreenToClient(hHandle, Result); end; function gfnrcWindowRectGet(hHandle: HWND): TRect; {2008-12-31: ウィンドウのRectを返す。 } begin GetWindowRect(hHandle, Result); end; function gfnrcClientRectGet(hHandle: HWND): TRect; begin if not(GetClientRect(hHandle, Result)) then begin FillChar(Result, SizeOf(Result), 0); end; end; (* type T_WinInfo = record Handle: HWND; Pos: TPoint; end; P_WinInfo = ^T_WinInfo; function gfnhToplevelWindowGetEx(ptPos: TPoint): HWND; {2009-01-11: ptPos上の可視のToplevelウィンドウを返す } function lfnb_MainWindowProc(hHandle: HWND; pInfo: P_WinInfo):BOOL; stdcall; //トップレベルウィンドウを列挙する begin if (PtInRect(gfnrcWindowRectGet(hHandle), pInfo^.Pos)) and (IsWindowVisible(hHandle)) //可視ウィンドウのみ then begin pInfo^.Handle := hHandle; Result := False; end else begin Result := True; end; end; var lr_Info: T_WinInfo; begin FillChar(lr_Info, SizeOf(lr_Info), 0); lr_Info.Pos := ptPos; EnumWindows(@lfnb_MainWindowProc, LPARAM(@lr_Info)); Result := lr_Info.Handle; end; function gfnhWindowGet(APoint : TPoint): HWND; //これは間違い {2007-09-07,08,09,2009-03-08: ptPosの点上にある可視ウィンドウを返す。 2009-03-09: 非可視の子ウィンドウがあるとそこで処理を打ち切っていたため正しい値を取得できてい なかった不具合を修正。 2007-09-08: コールバック関数で最初に親とするウィンドウのハンドルがセットされるのに気づかなかっ たためl_hWinHandleの値をみてそれが0でなければ、、という処理で間違っていたのを対処。 とりあえず全部の子ウィンドウを対象にチェック。 } function lfnb_ChildWindowProc(hHandle: HWND; pInfo: P_WinInfo): BOOL; stdcall; var lrc_Rect: TRect; begin GetWindowRect(hHandle, lrc_Rect); if (IsWindowVisible(hHandle)) and (PtInRect(lrc_Rect, pInfo^.Pos)) then begin pInfo^.Handle := hHandle; //点が列挙された子ウィンドウの中にあった //それが可視ウィンドウであればとりあえずセットしておく(まだ確定ではない) //まだ可能性はあるので続ける end; Result := True; end; var lr_Info: T_WinInfo; lh_Handle: HWND; begin lh_Handle := WindowFromPoint(APoint); if (lh_Handle = ChildWindowFromPoint(lh_Handle, gfnptScreenToClient(lh_Handle, APoint))) then begin //WindowFromPoint関数とChildWindowFromPoint関数で同じハンドルが返ってくるのであればそれで良い。 Result := lh_Handle; end else begin FillChar(lr_Info, SizeOf(lr_Info), 0); lr_Info.Pos := APoint; EnumChildWindows(gfnhTopLevelWindowGetEx(APoint), @lfnb_ChildWindowProc, LPARAM(@lr_Info)); if (lr_Info.Handle = 0) then begin Result := lh_Handle; end else begin Result := lr_Info.Handle; end; end; end; *) //APoint上にある可視ウィンドウを返す。 type T_WinPos = record Handle : HWND; //調べる点の上にあるウィンドウ Point : TPoint; //この位置にある一番手前の見えているウィンドウを取得する end; P_WinPos = ^T_WinPos; function EnumChildProc(hHandle: HWND; pWinPos: Pointer): BOOL; stdcall; var lh_Parent : HWND; lrc_Rect : TRect; begin Result := True; GetWindowRect(hHandle, lrc_Rect); if (IsWindowVisible(hHandle)) and (PtInRect(lrc_Rect, T_WinPos(pWinPos^).Point)) then begin lh_Parent := GetAncestor(hHandle, GA_PARENT); if (lh_Parent = T_WinPos(pWinPos^).Handle) then begin //直前に列挙された対象ウィンドウの子ウィンドウだった //hWindowを書き換える //子ウィンドウがあるかもしれないので処理を続ける T_WinPos(pWinPos^).Handle:= hHandle; end else begin //親ウィンドウが同じなら兄弟ウィンドウ。 //しかし列挙されるのは手前のウィンドウからなのでその場合はhTopは書き換ず処理を抜ける。 //親ウィンドウが直前のウィンドウでもない //おじさんおばさんウィンドウ、あるいはさらに遡ってのウィンドウであるのでこれまたhTopを書き換えず処理を抜ける Result := False; end; end; end; function gfnhWindowGet(APoint : TPoint) : HWND; //APoint上にあり一番手前にある見えているウィンドウのハンドルを返す。 var l_WinPos : T_WinPos; lh_Window, lh_CWindow : HWND; lpt_Client : TPoint; begin //WindowFromPointはAPointが無効ウィンドウ上にある場合はトップレベルウィンドウのハンドルを返す。 lh_Window := WindowFromPoint(APoint); lpt_Client := APoint; Windows.ScreenToClient(lh_Window, lpt_Client); lh_CWindow := ChildWindowFromPointEx(lh_Window, lpt_Client, CWP_SKIPINVISIBLE or CWP_SKIPTRANSPARENT); if (lh_Window = lh_CWindow) then begin //WindowFromPointとChildWindowFromPointExの戻り値が同じならそれで良い。 Result := lh_Window; end else begin FillChar(l_WinPos, SizeOf(l_WinPos), 0); l_WinPos.Handle := lh_Window; l_WinPos.Point := APoint; EnumChildWindows(lh_Window, @EnumChildProc, LPARAM(@l_WinPos)); Result := l_WinPos.Handle; end; end; function gfnhParentWindowGet(hHandle: HWND): HWND; //親ウィンドウのウィンドウハンドルを返す begin Result := GetAncestor(hHandle, GA_PARENT); //親ウィンドウ。hHandleがトップレベルウィンドウの場合GetDesktopWindowの値が返る // Result := GetParent(hHandle); end; function gfniProcessIDGet(hHandle: HWND): DWORD; begin GetWindowThreadProcessId(hHandle, @Result); end; function gfnsExeNameGet(hHandle: HWND): WideString; //ウィンドウハンドルからexeファイル名を返す //NT4.0以降対応。9x系には非対応。ただしエラーにはならないと思われ。 var lh_Process: THandle; lp_Buff: PWideChar; begin Result := ''; if (G_bIsNtOs) then begin lh_Process := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, gfniProcessIDGet(hHandle)); try lp_Buff := AllocMem((MAX_PATH +1) * 2); try //プロセスハンドルを渡すだけで実行ファイル名を得られた。モジュールのハンドルはいらないようだ。 if (GetModuleFileNameExW(lh_Process, 0, lp_Buff, MAX_PATH) <> 0) then begin Result := WideString(lp_Buff); end; finally FreeMem(lp_Buff); end; finally CloseHandle(lh_Process); end; end; end; function gfnsOsNameGet: WideString; {2007-12-13: OSが'2000', 'XP', 'Vista'のいずれであるかを返す } var lr_Info: TOSVersionInfo; begin Result := 'Unknown'; FillChar(lr_Info, SizeOf(lr_Info), 0); lr_Info.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);; if (GetVersionEx(lr_Info)) then begin with lr_Info do begin if (dwPlatformId = VER_PLATFORM_WIN32_NT) then begin //NT系 if (dwMajorVersion = 7) then begin Result := '7'; end else if (dwMajorVersion = 6) then begin Result := 'Vista'; end else if (dwMajorVersion = 5) then begin if (dwMinorVersion = 0) then begin Result := '2000'; end else begin Result := 'XP'; end; end else if (dwMajorVersion = 4) or (dwMajorVersion = 3) then begin Result := 'NT'; end; end else if (dwPlatformId = VER_PLATFORM_WIN32_WINDOWS) then begin //9x系 if (dwMinorVersion = 9) then begin Result := 'me'; end else if (dwMinorVersion = 1) then begin Result := '98'; end else if (dwMinorVersion = 0) then begin Result := '95'; end; end else if (dwPlatformId = VER_PLATFORM_WIN32s) then begin //Windows 3.1上のWin32s Result := 'Win32s'; end; end; end; end; function gfnbIsOSUpper2000: Boolean; //OSが2000以上であればTrueを返す。 var lr_Info: TOSVersionInfo; begin Result := False; FillChar(lr_Info, SizeOf(lr_Info), 0); lr_Info.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);; if (GetVersionEx(lr_Info)) then begin Result := (lr_Info.dwMajorVersion >= 5); end; end; //myNum.pas -------------------------------------------------------------------- function gfniStrToInt(sNum: String): Int64; //sNumを整数にして返す。 var li_Pos, i: Integer; ls_Tmp: String; begin sNum := UpperCase(Trim(sNum)); try Result := StrToInt64(sNum); except ls_Tmp := ''; for i := 1 to Length(sNum) do begin li_Pos := Pos(sNum[i], '$X-+0123456789ABCDEF'); if (li_Pos >= 15) then begin if (ls_Tmp[1] = '$') then begin ls_Tmp := ls_Tmp + sNum[i]; end else begin //頭に'$'を付け加えて変換できるようにする //頭に$がないと16進表記はエラーになるのでそれへの対処 ls_Tmp := '$' + ls_Tmp + sNum[i]; end; end else if (li_Pos >= 5) then begin ls_Tmp := ls_Tmp + sNum[i]; end else if ((li_Pos = 1) or (li_Pos = 2)) and (ls_Tmp = '') then begin //16進表記 ls_Tmp := '$'; //'x'や'X'ではだめ end else if ((li_Pos = 3) or (li_Pos = 4)) and (ls_Tmp = '') then begin //and (i = 1) でもよい //sNum[i]は'-+'のどれか ls_Tmp := sNum[i]; end else begin Break; end; end; if (ls_Tmp = '') then begin Result := 0; end else begin Result := StrToInt64Def(ls_Tmp, 0); end; end; end; function gfniRound(fNum: Extended): Int64; {2007-06-09: fNumを四捨五入して返す Delphiのヘルプからコピー } begin if (fNum >= 0) then begin Result := Trunc(fNum + 0.5); end else begin Result := Trunc(fNum - 0.5); end; end; function lfniCeil(X: Extended): Int64; begin Result := Trunc(X); if Frac(X) > 0 then Inc(Result); end; function lfniFloor(X: Extended): Int64; begin Result := Trunc(X); if Frac(X) < 0 then Dec(Result); end; function gfniRoundUp(fNum: Extended): Int64; {2007-06-09: fNumを切り上げて返す } begin if (fNum >= 0) then begin Result := lfniCeil(fNum); end else begin Result := lfniFloor(fNum); end; end; function gfniNumLimit(iNum: Integer; iMin, iMax: Integer): Integer; begin if (iMin = iMax) then begin Result := iMin; end else begin if (iNum < iMin) then begin Result := iMin; end else if (iNum > iMax) then begin Result := iMax; end else begin Result := iNum; end; end; end; function gfniNumLoop(iNum: Integer; iMin, iMax: Integer): Integer; {2007-10-05,28: iNum := gfniNumLoop(5, 2, 5); //⇒5 iNum := gfniNumLoop(6, 2, 5); //⇒2 iNum := gfniNumLoop(7, 2, 5); //⇒3 2→3→4→5 ↑←←←←←↓ 2007-10-28:間違っていたので書き直し } var li_Diff, li_Interval: Integer; begin if (iMin = iMax) then begin Result := iMin; end else begin li_Interval := iMax - iMin +1; //間隔 if (iNum < iMin) then begin li_Diff := Abs(iNum - iMin); Result := iMax - (li_Diff mod li_Interval) +1; end else if (iNum > iMax) then begin li_Diff := iNum - iMax; Result := iMin + (li_Diff mod li_Interval) -1; end else begin Result := iNum; end; end; end; function gfniMax(iNum: array of Integer): Integer; {2007-08-27: 引数の中の最大値を返す } var i: Integer; begin Result := iNum[0]; for i := 1 to High(iNum) do begin if (iNum[i] > Result) then Result := iNum[i]; end; end; function gfniMin(iNum: array of Integer): Integer; {2007-12-16: 引数の中の最小値を返す } var i: Integer; begin Result := iNum[0]; for i := 1 to High(iNum) do begin if (iNum[i] < Result) then Result := iNum[i]; end; end; //mySize.pas ------------------------------------------------------------------- function gfniRectWidth (rtRect: TRect): Integer; {2007-06-09: rtRectの幅を返す } begin with rtRect do begin Result := Right - Left; end; end; function gfniRectHeight(rtRect: TRect): Integer; {2007-06-09: rtRectの高さを返す } begin with rtRect do begin Result := Bottom - Top; end; end; function gfnrcRectCenter(rcParent, rcChild: TRect): TRect; {2007-09-26: rcChildがrcParentの真ん中にくるようなRectを返す } var li_Left, li_Top, li_Width, li_Height: Integer; begin li_Width := gfniRectWidth (rcChild); li_Height := gfniRectHeight(rcChild); li_Left := rcParent.Left + (gfniRectWidth (rcParent) - li_Width) div 2; li_Top := rcParent.Top + (gfniRectHeight(rcParent) - li_Height) div 2; Result := Rect(li_Left, li_Top, li_Left + li_Width, li_Top + li_Height); end; function gfnrcRectShift(rcRect: TRect; ptShift: TPoint): TRect; {2007-09-27: rcRectをptPoint移動した値を返す } begin with rcRect do begin Result := Rect(Left + ptShift.X, Top + ptShift.Y, Right + ptShift.X, Bottom + ptShift.Y); end; end; function gfnbCompleteRectInRect(rcCheck, rcRect: TRect): Boolean; //rcCheckが完全にrcRect内にあればTrueを返す begin if (rcCheck.Left >= rcRect.Left) and (rcCheck.Right <= rcRect.Right) and (rcCheck.Top >= rcRect.Top) and (rcCheck.Bottom <= rcRect.Bottom) then begin Result := True; end else begin Result := False; end; end; function gfnbRectInRect(rcCheck, rcRect: TRect): Boolean; //rcCheckがrcRect内に少しでもかかって入ればTrueを返す begin if (rcCheck.Left >= rcRect.Left) or (rcCheck.Right <= rcRect.Right) or (rcCheck.Top >= rcRect.Top) or (rcCheck.Bottom <= rcRect.Bottom) then begin Result := True; end else begin Result := False; end; end; function gfniAngleGet(ptStart, ptPos: TPoint): Integer; { ptStartを原点してptPosがどの方向(角度)にあるかを返す ptPosがptStartからダブルクリックで許容される範囲(の三倍)内にあれば-1を返す。 それ以外は0〜359の角度を返す。 http://nkiso.u-tokai.ac.jp/phys/matsuura/lecture/dyna/contents/triangle/triangle.asp } const lci_NOMOVE = 3; //マウスジェスチャーとして認識しない範囲 var li_X, li_Y: Integer; begin li_X := ptPos.X - ptStart.X; li_Y := ptStart.Y - ptPos.Y; //数学の座標とはY軸が逆なので反対にしている //ダブルクリックの範囲のlci_NOMOVE倍内であれば動いていないとみなす if (Abs(li_X) <= (GetSystemMetrics(SM_CXDOUBLECLK) * lci_NOMOVE)) then li_X := 0; if (Abs(li_Y) <= (GetSystemMetrics(SM_CYDOUBLECLK) * lci_NOMOVE)) then li_Y := 0; if (li_X = 0) then begin if (li_Y = 0) then begin Result := -1; end else if (li_Y > 0) then begin Result := 90; end else begin Result := 270; end; end else if (li_Y = 0) then begin if (li_X > 0) then begin Result := 0; end else begin Result := 180; end; end else begin Result := gfniRound(Arctan(li_Y / li_X) * (360 / (2 * Pi))); //Arctanはラジアン単位なので度に直す if (li_X > 0) and (li_Y > 0) then begin //第一象限 //そのまま end else if (li_X < 0) and (li_Y > 0) then begin //第二象限 Inc(Result, 180); //第四象限と同じ値が出るのでプラス180度 end else if (li_X < 0) and (li_Y < 0) then begin //第三象限 Inc(Result, 180); //第一象限と同じ値が出るのでプラス180度 end else {if (li_X < 0) and (li_Y > 0) then }begin //第四象限 Inc(Result, 360); //マイナスの角度が出るのでぐるっと360度足しこむ end; end; end; function gfnsCompasGet(ptStart, ptPos: TPoint): String; //上下左右を返す。 var li_Angle: Integer; begin li_Angle := gfniAngleGet(ptStart, ptPos); case li_Angle of -1: Result := ''; 0.. 45: Result := '右'; 46..135: Result := '上'; 136..225: Result := '左'; 226..315: Result := '下'; 316..359: Result := '右'; else Result := ''; //保険 end; end; //myFile.pas ------------------------------------------------------------------- function gfnsFilePathGet(sFile: WideString): WideString; //Unicode対応ExtractFilePath。 var i: Integer; begin //末尾の'\'がつくかつかないの法則が揺れると困るので処理を分けず独自関数のみにする // if (G_bIsNTOS) then begin Result := ''; if (sFile <> '') then begin for i := Length(sFile) downto 1 do begin if (sFile[i] = '\') or (sFile[i] = '/') then begin Result := Copy(sFile, 1, i); Break; end else if (sFile[i] = ':') then begin Result := Copy(sFile, 1, i) + '\'; Break; end; end; end; // end else begin // Result := ExtractFilePath(sFile); // end; end; function gfnsWorkFileNameGet(sExt : WideString) : WideString; //自身のファイル名の拡張子をsExtに変更して返す。 //主ファイル名にUnicodeな文字が入っていたらAnsiStringに変換し'?'を'_'に変更する。 //Unicode対応でない実行ファイルへ var ls_FullPath, //ファイル名も含めたフルパス ls_Path, ls_Main : WideString; //主ファイル名 begin if (sExt[1] <> '.') then begin sExt := '.' + sExt; end; if (G_bIsNTOS) then begin ls_FullPath := gfnsExeNameGet; ls_Main := gfnsFileExtChange(gfnsFileNameGet(ls_FullPath), ''); if (gfnbIsUnicode(ls_Main)) then begin ls_Path := gfnsFilePathGet(ls_FullPath); ls_Main := StringReplace(AnsiString(ls_Main), '?', '_', [rfReplaceAll]); Result := ls_Path + ls_Main + sExt; end else begin Result := gfnsFileExtChange(ls_FullPath, sExt); end; end else begin Result := gfnsFileExtChange(gfnsExeNameGet, sExt); end; end; function gfnsFileNameGet(sFile: WideString): WideString; var i, li_Len, li_Pos: Integer; begin if (G_bIsNTOS) then begin Result := ''; if (sFile <> '') then begin li_Len := Length(sFile); li_Pos := li_Len + 1; //sFileの最後が'\'であった場合への対策 for i := li_Len downto 1 do begin if (sFile[i] = '\') or (sFile[i] = '/') or(sFile[i] = ':') then begin Break; end; li_Pos := i; end; Result := Copy(sFile, li_Pos, MaxInt); end; end else begin Result := ExtractFileName(sFile); end; end; function gfnsFileExtChange(sFile, sExt: WideString): WideString; var i: Integer; begin if (G_bIsNTOS) then begin Result := ''; if (sExt <> '') and (sExt[1] <> '.') then begin //sExtが''だった時は拡張子削除。 //それ以外はピリオドがなければつけたす。 sExt := '.' + sExt; end; for i := Length(sFile) downto 1 do begin if (sFile[i] = '\') or (sFile[i] = ':') then begin //拡張子なし Break; end else if (sFile[i] = '.') then begin; //拡張子あり if (i > 1) then begin Result := Copy(sFile, 1, i -1) + sExt; end else begin Result := sExt; end; Exit; end; end; //sFileに拡張子があればここにはこない(↑でExitしている) Result := sFile + sExt; end else begin Result := ChangeFileExt(sFile, sExt); end; end; function gfnsExeNameGet: WideString; //WideString対応の自身の実行プログラム名を返す。 begin if (G_bIsNTOS) then begin Result := gfnsExeNameGet(Application.Handle); end else begin //Unicode文字が?に代替される場合へ対処 Result := StringReplace(ParamStr(0), '?', '_', [rfReplaceAll]); end; end; function gfnbFileExists(sFile: WideString): Boolean; var li_Attr: DWORD; begin Result := False; if (sFile = '') then begin Exit; end; if (G_bIsNTOS) then begin li_Attr := GetFileAttributesW(PWideChar(sFile)); Result := (li_Attr <> $FFFFFFFF) and ((li_Attr and FILE_ATTRIBUTE_DIRECTORY) = 0); end else begin Result := FileExists(sFile); end; end; function gfniFileSizeGet(hHandle: THandle): Int64; {2008-03-11: hHandleのファイルハンドルを持つファイルのサイズをByte単位で返す } var li_High, li_Low: DWORD; begin if (hHandle <> INVALID_HANDLE_VALUE) then begin li_Low := GetFileSize(hHandle, @li_High); Result := li_High * (Int64(MAXDWORD) +1) + li_Low; end else begin Result := 0; end; end; procedure gpcExecute(sFile: WideString); {2007-10-04: sFileを実行する } begin if (G_bIsNTOS) then begin ShellExecuteW(Application.Handle, nil, PWideChar(sFile), nil, nil, SW_SHOWNORMAL); end else begin ShellExecute(Application.Handle, nil, PAnsiChar(AnsiString(sFile)), nil, nil, SW_SHOWNORMAL); end; end; type TLangAndCodePage = record iLanguage: WORD; iCodePage: WORD; end; PLangAndCodePage = ^TLangAndCodePage; function gfnsFileVersionGet(sFile: WideString): WideString; //ファイルのバージョン情報を返す //http://www2.big.or.jp/~osamu/Delphi/Tips/key.cgi?key=13#0226.txt var li_Size, li_Reserved, li_Len: DWORD; lp_Buff, lp_Dat: Pointer; lp_LangPage: PLangAndCodePage; ls_FileInfo: WideString; begin Result := ''; if (G_bIsNTOS) then begin // 必要なバッファのサイズを取得 li_Size := GetFileVersionInfoSizeW(PWideChar(sFile), li_Reserved); if (li_Size > 0) then begin //メモリ確保 lp_Buff := AllocMem((li_Size +1) * 2); try if (GetFileVersionInfoW(PWideChar(sFile), 0, li_Size, lp_Buff)) then begin //変数情報ブロック内の変換テーブルを指定 if (VerQueryValueW(lp_Buff, '\VarFileInfo\Translation', Pointer(lp_LangPage), li_Len) and (li_Len > 0)) then begin ls_FileInfo := Format('\StringFileInfo\%.4x%.4x\', [lp_LangPage^.iLanguage, lp_LangPage^.iCodePage]); //ファイルバージョン if (VerQueryValueW(lp_Buff, PWideChar(ls_FileInfo + 'FileVersion'), lp_Dat, li_Len) and (li_Len > 0)) then begin Result := WideString(PWideChar(lp_Dat)); end; end; end; finally // 解放 FreeMem(lp_Buff); end; end; end else begin // 必要なバッファのサイズを取得 li_Size := GetFileVersionInfoSize(PAnsiChar(AnsiString(sFile)), li_Reserved); if (li_Size > 0) then begin //メモリ確保 lp_Buff := AllocMem(li_Size +1); try if (GetFileVersionInfo(PAnsiChar(AnsiString(sFile)), 0, li_Size, lp_Buff)) then begin //変数情報ブロック内の変換テーブルを指定 if (VerQueryValue(lp_Buff, '\VarFileInfo\Translation', Pointer(lp_LangPage), li_Len) and (li_Len > 0)) then begin ls_FileInfo := Format('\StringFileInfo\%.4x%.4x\', [lp_LangPage^.iLanguage, lp_LangPage^.iCodePage]); //ファイルバージョン if (VerQueryValue(lp_Buff, PAnsiChar(AnsiString(ls_FileInfo + 'FileVersion')), lp_Dat, li_Len) and (li_Len > 0)) then begin Result := AnsiString(PAnsiChar(lp_Dat)); end; end; end; finally // 解放 FreeMem(lp_Buff); end; end; end; end; function gfnsFileVersionGet: WideString; //自アプリのファイルバージョン。 begin Result := gfnsFileVersionGet(gfnsExeNameGet); end; function gfnsProductNameGet(sFile: WideString): WideString; //自アプリの製品名。 var li_Size, li_Reserved, li_Len: DWORD; lp_Buff, lp_Dat: Pointer; lp_LangPage: PLangAndCodePage; ls_FileInfo: WideString; begin Result := ''; if (G_bIsNTOS) then begin // 必要なバッファのサイズを取得 li_Size := GetFileVersionInfoSizeW(PWideChar(sFile), li_Reserved); if (li_Size > 0) then begin //メモリ確保 lp_Buff := AllocMem((li_Size +1) * 2); try if (GetFileVersionInfoW(PWideChar(sFile), 0, li_Size, lp_Buff)) then begin //変数情報ブロック内の変換テーブルを指定 if (VerQueryValueW(lp_Buff, '\VarFileInfo\Translation', Pointer(lp_LangPage), li_Len) and (li_Len > 0)) then begin ls_FileInfo := Format('\StringFileInfo\%.4x%.4x\', [lp_LangPage^.iLanguage, lp_LangPage^.iCodePage]); //製品名 if (VerQueryValueW(lp_Buff, PWideChar(ls_FileInfo + 'ProductName'), lp_Dat, li_Len) and (li_Len > 0)) then begin Result := WideString(PWideChar(lp_Dat)); end; end; end; finally // 解放 FreeMem(lp_Buff); end; end; end else begin // 必要なバッファのサイズを取得 li_Size := GetFileVersionInfoSize(PAnsiChar(AnsiString(sFile)), li_Reserved); if (li_Size > 0) then begin //メモリ確保 lp_Buff := AllocMem(li_Size +1); try if (GetFileVersionInfo(PAnsiChar(AnsiString(sFile)), 0, li_Size, lp_Buff)) then begin //変数情報ブロック内の変換テーブルを指定 if (VerQueryValue(lp_Buff, '\VarFileInfo\Translation', Pointer(lp_LangPage), li_Len) and (li_Len > 0)) then begin ls_FileInfo := Format('\StringFileInfo\%.4x%.4x\', [lp_LangPage^.iLanguage, lp_LangPage^.iCodePage]); //製品名 if (VerQueryValue(lp_Buff, PAnsiChar(AnsiString(ls_FileInfo + 'ProductName')), lp_Dat, li_Len) and (li_Len > 0)) then begin Result := AnsiString(PAnsiChar(lp_Dat)); end; end; end; finally // 解放 FreeMem(lp_Buff); end; end; end; end; function gfnsProductNameGet: WideString; begin Result := gfnsProductNameGet(gfnsExeNameGet); end; procedure gpcFileWriteText(sFile, sText: WideString); var lh_Handle: THandle; li_Count: DWORD; ls_Text: AnsiString; begin if (G_bIsNTOS) then begin lh_Handle := CreateFileW( PWideChar(sFile), //ファイル名 GENERIC_WRITE, //アクセスモード 0, //共有モード nil, //セキュリティ CREATE_ALWAYS, //作成方法 FILE_ATTRIBUTE_NORMAL, //ファイル属性 0 //テンプレート ); end else begin lh_Handle := CreateFile( PAnsiChar(AnsiString(sFile)), //ファイル名 GENERIC_WRITE, //アクセスモード 0, //共有モード nil, //セキュリティ CREATE_ALWAYS, //作成方法 FILE_ATTRIBUTE_NORMAL, //ファイル属性 0 //テンプレート ); end; try if (lh_Handle <> INVALID_HANDLE_VALUE) then begin //UnicodeではなくShift JISで書き込む ls_Text := sText; WriteFile(lh_Handle, PAnsiChar(ls_Text)^, Length(ls_Text), li_Count, nil); end; finally CloseHandle(lh_Handle); end; end; //myGraphic.pas ---------------------------------------------------------------- type TFileStreamW = class(THandleStream) public constructor Create(const FileName: WideString; Mode: Word); overload; destructor Destroy; override; end; constructor TFileStreamW.Create(const FileName: WideString; Mode: Word); //TFileStreamのUnicode版  var li_AccessMode, li_ShareMode: DWORD; begin if (Mode = fmCreate) then begin inherited Create(CreateFileW( PWideChar(FileName), //ファイル名 GENERIC_READ or GENERIC_WRITE, //アクセスモード 0, //共有モード nil, //セキュリティ OPEN_ALWAYS, //作成方法 FILE_ATTRIBUTE_NORMAL, //ファイル属性 0 //テンプレート )); end else begin //アクセスモード li_AccessMode := GENERIC_READ; if ((Mode and fmOpenWrite) <> 0) then begin li_AccessMode := li_AccessMode or GENERIC_WRITE; end; {$WARN SYMBOL_PLATFORM OFF} //共有モード li_ShareMode := 0; if (Mode >= fmShareExclusive) then begin Dec(Mode, $10); end; if ((Mode and (fmShareDenyRead - $10)) <> 0) then begin //読み込みは禁止=書き込みはOK li_ShareMode := FILE_SHARE_WRITE; end; if ((Mode and (fmShareDenyWrite - $10)) <> 0) then begin //書き込みは禁止=読み込みはOK li_ShareMode := li_ShareMode or FILE_SHARE_READ; end; {$WARN SYMBOL_PLATFORM ON} inherited Create(CreateFileW( PWideChar(FileName), li_AccessMode, li_ShareMode, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 )); end; if (FHandle = Integer(INVALID_HANDLE_VALUE)) then begin //エラーメッセージはUnicode対応ではない。 raise EFCreateError.CreateResFmt(@SFCreateError, [FileName]); end; end; destructor TFileStreamW.Destroy; begin if (FHandle >= 0) then CloseHandle(FHandle); inherited Destroy; end; //------------------------------------------------------------------------------ procedure TMyBitmap.SaveToFile(const Filename: WideString); var l_Stream: TStream; begin if (G_bIsNtOs) then begin l_Stream := TFileStreamW.Create(Filename, fmCreate); try SaveToStream(l_Stream); finally l_Stream.Free; end; end else begin inherited SaveToFile(AnsiString(Filename)); end; end; function gfnclColorRevers(clColor: TColor): TColor; {2007-06-18: clColorの反転色を返す } var li_Color: Longint; li_Red, li_Green, li_Blue: Integer; begin li_Color := ColorToRGB(clColor); li_Red := (li_Color and $0000FF); li_Green := (li_Color and $00FF00) div $000100; li_Blue := (li_Color and $FF0000) div $010000; Result := (($FF - li_Blue) * $010000) + (($FF - li_Green) * $000100) + ($FF - li_Red); end; procedure gpcColorRGBToHLS(iRed, iGreen, iBlue: BYTE; var iHue, iLuminance, iSaturation: WORD; iMaxHue, iMaxLuminance, iMaxSaturation: WORD); {2009-09-13: RGBをHLSに変換。 APIのColorRGBToHLSがH,L,Sの範囲が0〜240で直観的でないので自作。 http://www.pannoki.com/tips/ index.php?RGB%20to%20HLS http://inugashira.exblog.jp/9551741/ http://support.microsoft.com/kb/29240/ja } const lci_MAXRGB = High(BYTE); //R,G,Bの取れる値の範囲(256) var li_Max, li_Min: WORD; li_Hue, li_Saturation: Integer; lf_RDelta, lf_GDelta, lf_BDelta: Extended; begin if (iRed = iGreen) and (iGreen = iBlue) then begin //全部同じということは無彩色(黒か白かグレー)であるので色彩(Hue)と彩度(Saturation)は無意味 iSaturation := 0; iHue := 0; iLuminance := gfniRound(iRed / lci_MAXRGB * iMaxLuminance); end else begin li_Max := gfniMax([iRed, iGreen, iBlue]); li_Min := gfniMin([iRed, iGreen, iBlue]); //明度 iLuminance := WORD(gfniRound((li_Max + li_Min) / 2 / lci_MAXRGB * iMaxLuminance)); //彩度 if (iLuminance <= (iMaxLuminance div 2)) then begin li_Saturation := gfniRound((((li_Max - li_Min) * iMaxSaturation) + ((li_Max + li_Min) / 2)) / (li_Max + li_Min)); end else begin li_Saturation := gfniRound((((li_Max - li_Min) * iMaxSaturation) + ((2 * lci_MAXRGB - li_Max - li_Min) / 2)) / (2 * lci_MAXRGB - li_Max - li_Min)); end; iSaturation := WORD(gfniNumLimit(li_Saturation, 0, iMaxSaturation)); //Hue lf_RDelta := ( ((li_Max - iRed) * (iMaxHue / 6)) + ((li_Max - li_Min) / 2) ) / (li_Max - li_Min); lf_GDelta := ( ((li_Max - iGreen) * (iMaxHue / 6)) + ((li_Max - li_Min) / 2) ) / (li_Max - li_Min); lf_BDelta := ( ((li_Max - iBlue) * (iMaxHue / 6)) + ((li_Max - li_Min) / 2) ) / (li_Max - li_Min); if (iRed = li_Max) then begin li_Hue := gfniRound(lf_BDelta - lf_GDelta); end else if (iGreen = li_Max) then begin li_Hue := gfniRound((iMaxHue / 3) + lf_RDelta - lf_BDelta); end else {if (iBlue = li_Max) then} begin li_Hue := gfniRound(((2 * iMaxHue) / 3) + lf_GDelta - lf_RDelta); end; iHue := WORD(gfniNumLoop(li_Hue, 0, iMaxHue -1)); end; end; procedure gpcColorRGBToHLS(iRed, iGreen, iBlue: BYTE; var iHue, iLuminance, iSaturation: WORD); //Hは0〜360 //LとSは0〜100 const lci_MAXHUE = 360; lci_MAXLUMINANCE = 100; lci_MAXSATURATION = 100; begin gpcColorRGBToHLS(iRed, iGreen, iBlue, iHue, iLuminance, iSaturation, lci_MAXHUE, lci_MAXLUMINANCE, lci_MAXSATURATION); end; procedure gpcColorRGBToHSV(iRed, iGreen, iBlue: BYTE; var iHue, iValue, iSaturation: WORD; iMaxHue, iMaxValue, iMaxSaturation: WORD); const lci_MAXRGB = High(BYTE) +1; //R,G,Bの取れる値の範囲(256) var li_Max, li_Min: WORD; li_Hue: Integer; lf_RDelta, lf_GDelta, lf_BDelta: Extended; begin if (iRed = iGreen) and (iGreen = iBlue) then begin iHue := 0; iSaturation := 0; iValue := gfniRound(iRed / lci_MAXRGB * iMaxValue); end else begin li_Max := gfniMax([iRed, iGreen, iBlue]); li_Min := gfniMin([iRed, iGreen, iBlue]); iSaturation := WORD(gfniNumLimit(gfniRound((li_Max - li_Min) / li_Max * iMaxSaturation), 0, iMaxSaturation)); iValue := WORD(gfniNumLimit(gfniRound(li_Max / lci_MAXRGB * iMaxValue), 0, iMaxValue)); //Hue lf_RDelta := ( ((li_Max - iRed) * (iMaxHue / 6)) + ((li_Max - li_Min) / 2) ) / (li_Max - li_Min); lf_GDelta := ( ((li_Max - iGreen) * (iMaxHue / 6)) + ((li_Max - li_Min) / 2) ) / (li_Max - li_Min); lf_BDelta := ( ((li_Max - iBlue) * (iMaxHue / 6)) + ((li_Max - li_Min) / 2) ) / (li_Max - li_Min); if (iRed = li_Max) then begin li_Hue := gfniRound(lf_BDelta - lf_GDelta); end else if (iGreen = li_Max) then begin li_Hue := gfniRound((iMaxHue / 3) + lf_RDelta - lf_BDelta); end else {if (iBlue = li_Max) then} begin li_Hue := gfniRound(((2 * iMaxHue) / 3) + lf_GDelta - lf_RDelta); end; iHue := WORD(gfniNumLoop(li_Hue, 0, iMaxHue -1)); end; end; //myList.pas ------------------------------------------------------------------- function gfnbIsIncludeList(sValue: String; slList: TStrings): Boolean; {2007-10-17: slList中にsValueがあればTrueを返す 大文字小文字の違いは無視 } var i: Integer; begin Result := False; for i := 0 to slList.Count -1 do begin if (AnsiCompareText(sValue, slList[i]) = 0) then begin Result := True; Break; end; end; end; function gfnbIsIncludeList(sValue: String; slList: array of String): Boolean; //slList中にsValueがあればTrueを返す //大文字小文字の違いは無視 var i: Integer; begin Result := False; for i := Low(slList) to High(slList) do begin if (AnsiCompareText(sValue, slList[i]) = 0) then begin Result := True; Break; end; end; end; //------------------------------------------------------------------------------ //myMessageBox function gfniMessageBox(const sMsg, sTitle: String; const iStyle: UINT): Integer; {2007-10-06: Unicode対応のMessageBox。 最終的にこの関数が呼ばれる。 } begin //iStyleに0を指定した場合はMB_OKを指定したのと同じ Result := MessageBox(Application.Handle, PChar(sMsg), PChar(sTitle), iStyle or MB_SETFOREGROUND); end; function gfniMessageBoxYesNo(const sMsg, sTitle: String): Integer; {2008-03-08: MessageBox。YesとNoボタン。 } begin Result := gfniMessageBox(sMsg, sTitle, MB_YESNO or MB_APPLMODAL{ or MB_ICONQUESTION}); end; procedure gpcShowMessage(sMsg, sTitle: String); begin gfniMessageBox(sMsg, sTitle, MB_OK); end; //------------------------------------------------------------------------------ const WC_NO_BEST_FIT_CHARS = $00000400; function gfnbIsUnicode(sSrc: WideString): Boolean; {2007-11-05,2009-02-12: sSrcにウムラウトのようなUnicode文字があればTrueを返す http://yokohama.cool.ne.jp/chokuto/urawaza/api/WideCharToMultiByte.html 0x00000400 (WC_NO_BEST_FIT_CHARS) Windows 2000/XP:直接マルチバイト文字に変換できない文字をデフォルトキャラクタに置きかえます。 2009-02-12: ResultをWideChartoMultiByteに直接渡すのでなくlb_Boolを介するように変更。 BooleanとLongBoolで型が違うため実行時エラーになってしまうことがあるため。 } var lb_Bool: LongBool; begin WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, PWideChar(sSrc), -1, nil, 0, nil, @lb_Bool); Result := lb_Bool; end; function gfnsWideToUtf7(sSrc: WideString): AnsiString; {2008-06-06: WideStringをUTF-7にエンコードして返す } var li_Len: Integer; lp_Buff: PAnsiChar; begin //WC_COMPOSITECHECKはNG li_Len := WideCharToMultiByte(CP_UTF7, 0, PWideChar(sSrc), -1, nil, 0, nil, nil); lp_Buff := AllocMem(li_Len + 1); try WideCharToMultiByte(CP_UTF7, 0, PWideChar(sSrc), -1, lp_Buff, li_Len, nil, nil); Result := AnsiString(lp_Buff); finally FreeMem(lp_Buff); end; end; function gfnsUtf7ToWide(sSrc: AnsiString): WideString; {2008-06-06: UTF-7でエンコードされている文字列をWideStringにして返す } var li_Len: Integer; lp_Buff: PWideChar; begin li_Len := MultiByteToWideChar(CP_UTF7, 0, PAnsiChar(sSrc), -1, nil, 0); lp_Buff := AllocMem((li_Len + 1) * 2); try MultiByteToWideChar(CP_UTF7, 0, PAnsiChar(sSrc), -1, lp_Buff, li_Len); Result := WideString(lp_Buff); finally FreeMem(lp_Buff); end; end; //UTF-16LE⇔UTF-8 function gfnsWideToUTF8(sSrc: WideString): UTF8String; //WideStringをUTF-8にエンコードして返す。 var li_Len: Integer; lp_Buff: PAnsiChar; begin if (G_bIsNtOs) then begin li_Len := WideCharToMultiByte(CP_UTF8, 0, PWideChar(sSrc), -1, nil, 0, nil, nil); lp_Buff := AllocMem(li_Len + 1); try WideCharToMultiByte(CP_UTF8, 0, PWideChar(sSrc), -1, lp_Buff, li_Len +1, nil, nil); Result := UTF8String(lp_Buff); finally FreeMem(lp_Buff); end; end else begin Result := Utf8Encode(sSrc); end; end; function gfnsUTF8ToWide(sSrc: UTF8String): WideString; //UTF-8でエンコードされている文字列をWideStringにして返す。 var li_Len: Integer; lp_Buff: PWideChar; begin if (G_bIsNtOs) then begin li_Len := MultiByteToWideChar(CP_UTF8, 0, PAnsiChar(sSrc), -1, nil, 0); lp_Buff := AllocMem((li_Len + 1) * 2); try MultiByteToWideChar(CP_UTF8, 0, PAnsiChar(sSrc), -1, lp_Buff, li_Len); Result := WideString(lp_Buff); finally FreeMem(lp_Buff); end; end else begin Result := Utf8Decode(sSrc); end; end; function gfnsWideToAnsi(sSrc: WideString): AnsiString; {2008-06-03,12-28,2009-02-12: 合成文字をきちんとあつかってAnsiStringに変換。 例)「か゛」→「が」みたいな感じで。 2009-02-12:合成文字のみの場合にきちんと変換されていなかった不具合の修正。 2008-12-28:gfnsWideToStr→gfnsWideToAnsi } var li_Len: Integer; lp_Buff: PAnsiChar; begin //WC_COMPOSITECHECKが肝 li_Len := WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK{ or WC_SEPCHARS}, PWideChar(sSrc), -1, nil, 0, nil, nil); Inc(li_Len); lp_Buff := AllocMem(li_Len); try WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK{ or WC_SEPCHARS}, PWideChar(sSrc), -1, lp_Buff, li_Len, nil, nil); Result := AnsiString(lp_Buff); finally FreeMem(lp_Buff); end; end; //myClipbrd.pas ---------------------------------------------------------------- procedure gpcStrToClipboard(sStr: String); var li_WLen, li_Len: Integer; ls_WText: WideString; ls_Text: AnsiString; lh_Mem: THandle; lp_Data: Pointer; begin if not(G_bIsNtOs) then begin Clipboard.AsText := sStr; end else begin //NT系OSならsStrはUTF-8にエンコードされている ls_WText := gfnsUtf8ToWide(sStr); li_WLen := (Length(ls_WText) + 1) * 2; ls_Text := gfnsWideToAnsi(ls_WText); li_Len := Length(ls_Text) + 1; if (ls_WText <> '') then begin if (OpenClipboard(Application.Handle)) then begin try EmptyClipboard; //CF_UNICODETEXT lh_Mem := GlobalAlloc(GHND or GMEM_SHARE, li_WLen); lp_Data := GlobalLock(lh_Mem); lstrcpyW(lp_Data, PWideChar(ls_WText)); GlobalUnlock(lh_Mem); SetClipboardData(CF_UNICODETEXT, lh_Mem); //CF_TEXT lh_Mem := GlobalAlloc(GHND or GMEM_SHARE, li_Len); lp_Data := GlobalLock(lh_Mem); lstrcpy(lp_Data, PChar(ls_Text)); GlobalUnlock(lh_Mem); SetClipboardData(CF_TEXT, lh_Mem); finally CloseClipboard; end; end; end; end; end; //------------------------------------------------------------------------------ initialization G_bIsNtOs := gfnbIsNtOs; // G_bIsNtOs := False; end.