unit main; //{$DEFINE DEBUG} interface uses Windows, Messages, SysUtils, ActnList, AppEvnts, Buttons, Classes, ComCtrls, Controls, Dialogs, ExtCtrls, Forms, Graphics, Grids, ImgList, Menus, StdCtrls, ToolWin, myEdit, myLabel, // myType, myWStrings; type TApp_TOOLLFont = class(TForm) ActionList1: TActionList; Action_TextReplace: TAction; Action_TextClear: TAction; Action_TextCheckClipboard: TAction; Action_TextWrap: TAction; Action_FontSel: TAction; Action_FontSizeUp: TAction; Action_FontSizeDown: TAction; Action_FileExit: TAction; Action_EditUndo: TAction; Action_EditRedo: TAction; Action_EditCut: TAction; Action_EditCopy: TAction; Action_EditPaste: TAction; Action_EditDelete: TAction; Action_EditSelectAll: TAction; Action_HelpVersionInfo: TAction; ToolBar1: TToolBar; ToolButton_TextReplace: TToolButton; ToolButton_TextClear: TToolButton; ToolButton_TextCheckClipboard: TToolButton; ToolButton_Spc1: TToolButton; ToolButton_EditUndo: TToolButton; ToolButton_EditRedo: TToolButton; ToolButton_EditCut: TToolButton; ToolButton_EditCopy: TToolButton; ToolButton_EditPaste: TToolButton; ToolButton_EditDelete: TToolButton; ToolButton_EditSelectAll: TToolButton; ToolButton_Spc2: TToolButton; ToolButton_TextWrap: TToolButton; ToolButton_FontSel: TToolButton; ToolButton_FontSizeUp: TToolButton; ToolButton_FontSizeDown: TToolButton; ToolButton_Spc3: TToolButton; ToolButton_HelpVersionInfo: TToolButton; Memo_Text: TMyMemo; Panel_Status: TPanel; Shape_Bottom: TShape; Label_StatusChar: TMyLabel; Bevel_Spc1: TBevel; Label_StatusAnsi: TMyLabel; Bevel_Spc2: TBevel; Label_StatusUnicode: TMyLabel; Bevel_Spc3: TBevel; Label_StatusUtf8: TMyLabel; FontDialog1: TFontDialog; ImageList1: TImageList; PopupMenu_Main: TPopupMenu; mniPEdit_Undo: TMenuItem; mniPEdit_Redo: TMenuItem; mniPLine_1: TMenuItem; mniPEdit_Cut: TMenuItem; mniPEdit_Copy: TMenuItem; mniPEdit_Paste: TMenuItem; mniPEdit_Delete: TMenuItem; mniPLine_2: TMenuItem; mniPEdit_SelectAll: TMenuItem; mniPLine_5: TMenuItem; __mniPEdit_Tab: TMenuItem; procedure Action_TextReplaceExecute (Sender: TObject); procedure Action_TextClearExecute (Sender: TObject); procedure Action_FontSizeUpExecute (Sender: TObject); procedure Action_FileExitExecute (Sender: TObject); procedure Action_EditUndoExecute (Sender: TObject); procedure Action_EditRedoExecute (Sender: TObject); procedure Action_EditCutExecute (Sender: TObject); procedure Action_EditCopyExecute (Sender: TObject); procedure Action_EditPasteExecute (Sender: TObject); procedure Action_EditDeleteExecute (Sender: TObject); procedure Action_EditSelectAllExecute (Sender: TObject); procedure Action_FontSelExecute (Sender: TObject); procedure Action_HelpVersionInfoExecute(Sender: TObject); procedure actNop (Sender: TObject); procedure FormCreate (Sender: TObject); procedure FormDestroy (Sender: TObject); procedure Memo_TextKeyDown (Sender: TObject; var Key: Word; Shift: TShiftState); procedure Memo_TextKeyUp (Sender: TObject; var Key: Word; Shift: TShiftState); procedure Memo_TextSelectionChange(Sender: TObject); procedure PopupMenu_MainPopup (Sender: TObject); procedure __mniPEdit_TabClick (Sender: TObject); procedure Action_TextWrapExecute(Sender: TObject); procedure Memo_TextMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean); procedure Action_TextCheckClipboardExecute(Sender: TObject); private { Private 宣言 } FiKey : Word; FsCopyText : WideString; //クリップボード監視 FhNextHandle : HWND; procedure FEntryClipboardViewer; procedure FRemoveClipboardViewer; procedure WMDrawClipboard(var Msg: TWMDrawClipboard); message WM_DRAWCLIPBOARD; procedure WMChangeCBChain(var Msg: TWMChangeCBChain); message WM_CHANGECBCHAIN; function FDisposeShortCut(var Key: Word; Shift: TShiftState): Boolean; procedure FLoadIni; procedure FSaveIni; public { Public 宣言 } end; var App_TOOLLFont : TApp_TOOLLFont; implementation uses {$IFDEF DEBUG} myDebug, {$ENDIF} Clipbrd, CommCtrl, RichEdit, myApp, myClipbrd, myHelpVersionInfo, myIniFile, myNum, myWindow; {$R *.dfm} //------------------------------------------------------------------------------ //クリップボード監視ルーチン procedure TApp_TOOLLFont.FEntryClipboardViewer; begin FhNextHandle := SetClipboardViewer(Self.Handle); if (FhNextHandle = 0) and (GetLastError <> 0) then begin {エラーだったら} //クリップボードの更新チェックの登録処理に失敗した場合の処理 //ShowMessage('クリップボードの更新チェックの登録処理に失敗しました'); end; end; procedure TApp_TOOLLFont.FRemoveClipboardViewer; begin //クリップボード監視処理の破棄 ChangeClipboardChain(Self.Handle, FhNextHandle); end; procedure TApp_TOOLLFont.WMDrawClipboard(var Msg: TWMDrawClipboard); //クリップボード更新フック //更新された後に流れてくる。 //アプリが立ち上がった瞬間も流れる begin inherited; if (FhNextHandle <> 0) then begin //次の監視ウィンドウへメッセージ送信 SendMessage(FhNextHandle, WM_DRAWCLIPBOARD, 0, 0); end; if (Action_TextCheckClipboard.Checked) then begin Action_TextReplaceExecute(nil); end; PopupMenu_MainPopup(nil); end; procedure TApp_TOOLLFont.WMChangeCBChain(var Msg: TWMChangeCBChain); begin if (Msg.Remove = FhNextHandle) then begin //クリップボードをフックしている次のウィンドウがフックを解除した FhNextHandle := Msg.Next; end; if (FhNextHandle <> 0) then begin //次のビューアへメッセージ送信 SendMessage(FhNextHandle, WM_CHANGECBCHAIN, Msg.Remove, Msg.Next); end; end; procedure TApp_TOOLLFont.Action_TextCheckClipboardExecute(Sender: TObject); //クリップボードの監視を一旦解除して再度監視するようにすることで監視できなくなっ //しまうことへ対処。 begin //クリップボード監視を解除 FRemoveClipboardViewer; //クリップボード監視 FEntryClipboardViewer; end; //------------------------------------------------------------------------------ function TApp_TOOLLFont.FDisposeShortCut(var Key: Word; Shift: TShiftState): Boolean; begin Result := False; if (ssCtrl in Shift) then begin FiKey := Key; case Key of VK_UP, // VK_DOWN, //ビープ音が鳴るのを防ぐため //RichEditコントロールが持つ以下のショートカットキーを無効化。 Ord('E'), //センタリング Ord('J'), //自動 Ord('L'), //左詰 Ord('R'), //右詰 Ord('+'), //上付き文字 Ord('='), // Ord('1'), //行間調整 Ord('2'), //行間調整 Ord('5') //行間調整 :begin Result := True; end; end; end; if (Result) then begin Key := 0; end; end; procedure TApp_TOOLLFont.Action_FontSizeUpExecute(Sender: TObject); const lci_MINSIZE = 8; lci_MAXSIZE = 144; lci_SHIFTUP = 5; var li_Size : Integer; li_Up : Integer; begin li_Size := Memo_Text.Font.Size; if (gfnbKeyState(VK_SHIFT)) then begin li_Up := lci_SHIFTUP; end else begin li_Up := 1; end; if (Sender = Action_FontSizeUp) then begin Inc(li_Size, li_Up); end else if (Sender = Action_FontSizeDown) then begin Dec(li_Size, li_Up); end else begin Exit; end; li_Size := gfniNumLimit(li_Size, lci_MINSIZE, lci_MAXSIZE); if (li_Size <> Memo_Text.Font.Size) then begin Memo_Text.Font.Size := li_Size; end; end; procedure TApp_TOOLLFont.Memo_TextMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean); begin if not(ssCtrl in Shift) then begin Exit; end else begin Handled := True; end; if (WheelDelta > 0) then begin Action_FontSizeUpExecute(Action_FontSizeUp); end else begin Action_FontSizeUpExecute(Action_FontSizeDown); end; end; procedure TApp_TOOLLFont.Memo_TextKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin FDisposeShortCut(Key, Shift); if (ssCtrl in Shift) then begin case FiKey of VK_UP :begin Action_FontSizeUpExecute(Action_FontSizeUp); end; VK_DOWN :begin Action_FontSizeUpExecute(Action_FontSizeDown); end; end; end else begin case Key of VK_TAB :begin Key := 0; end; end; end; end; procedure TApp_TOOLLFont.Memo_TextKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin Memo_TextSelectionChange(nil); end; //http://mrxray.on.coocan.jp/Halbow/Notes/N016.html function NibbleToBinaryStr(value:Byte):string; const Bit:array[0..1] of Char = ('0','1'); var i:integer; begin SetLength(result,4); for i := 0 to 3 do begin result[4-i] := Bit[value and 1]; value := value shr 1; end; end; function ByteToBinaryStr(value:Byte):string; begin result := NibbleToBinaryStr(value shr 4) + NibbleToBinaryStr(value and $F); end; procedure TApp_TOOLLFont.Memo_TextSelectionChange(Sender: TObject); function _GetUtf8Code(sStr: WideString): WideString; function _GetBin(pBuff: PAnsiChar; iCount: Integer): AnsiString; var i: Integer; begin Result := ''; for i := 0 to iCount-1 do begin Result := Result + ' ' + ByteToBinaryStr(Ord(pBuff[i])); end; end; var i: Integer; ls_Utf8 : Utf8String; ls_Bin : AnsiString; begin Result := ''; ls_Utf8 := gfnsWideToUtf8(sStr); for i := 1 to Length(ls_Utf8) do begin Result := WideFormat('%s%.2x', [Result, Ord(ls_Utf8[i])]); end; if (Result <> '') then begin ls_Bin := _GetBin(PAnsiChar(ls_Utf8), Length(ls_Utf8)); Result := WideFormat('UTF8 U+%s %s', [Result, Trim(ls_Bin)]); end; end; var ls_Str : WideString; ls_SJis : AnsiString; li_Code : Longint; begin if (Tag = 0) or (Application.Terminated) then begin Exit; end; PopupMenu_MainPopup(nil); //キャラクタコード表示 ls_Str := Memo_Text.StrCopy(1); if (ls_Str = '') then begin Label_StatusChar.ParentColor := True; Label_StatusChar.Caption := ''; Label_StatusAnsi.Caption := ''; Label_StatusUnicode.Caption := ''; Label_StatusUtf8.Caption := ''; end else begin li_Code := Ord(ls_Str[1]); case li_Code of $D800..$DBFF :begin //サロゲートペア //http://codezine.jp/article/detail/1592 ls_Str := Memo_Text.StrCopy(2); Label_StatusUnicode.Caption := WideFormat('UTF16 U+%.5x(%.4x+%.4x)', [(Ord(ls_Str[1]) - $D800) * $400 + (Ord(ls_Str[2]) - $DC00) + $10000, Ord(ls_Str[1]), Ord(ls_Str[2])]); Label_StatusUtf8.Caption := _GetUtf8Code(ls_Str); end else begin Label_StatusUnicode.Caption := WideFormat('UTF16 U+%.4x', [Ord(ls_Str[1])]); Label_StatusUtf8.Caption := _GetUtf8Code(ls_Str); end; end; case li_Code of $0: Label_StatusChar.Caption := 'NUL'; $1: Label_StatusChar.Caption := 'SOH'; $2: Label_StatusChar.Caption := 'STX'; $3: Label_StatusChar.Caption := 'ETX'; $4: Label_StatusChar.Caption := 'EOT'; $5: Label_StatusChar.Caption := 'ENQ'; $6: Label_StatusChar.Caption := 'ACK'; $7: Label_StatusChar.Caption := 'BEL'; $8: Label_StatusChar.Caption := 'BS'; $9: Label_StatusChar.Caption := 'Tab'; $A: Label_StatusChar.Caption := 'LF'; $B: Label_StatusChar.Caption := 'VT'; $C: Label_StatusChar.Caption := 'FF'; $D: Label_StatusChar.Caption := 'CR'; $E: Label_StatusChar.Caption := 'SO'; $F: Label_StatusChar.Caption := 'SI'; $10: Label_StatusChar.Caption := 'DLE'; $11: Label_StatusChar.Caption := 'DC1'; $12: Label_StatusChar.Caption := 'DC2'; $13: Label_StatusChar.Caption := 'DC3'; $14: Label_StatusChar.Caption := 'DC4'; $15: Label_StatusChar.Caption := 'NAK'; $16: Label_StatusChar.Caption := 'SYN'; $17: Label_StatusChar.Caption := 'ETB'; $18: Label_StatusChar.Caption := 'CAN'; $19: Label_StatusChar.Caption := 'EM'; $1A: Label_StatusChar.Caption := 'SUB'; $1B: Label_StatusChar.Caption := 'ESC'; $1C: Label_StatusChar.Caption := 'FS'; $1D: Label_StatusChar.Caption := 'GS'; $1E: Label_StatusChar.Caption := 'RS'; $1F: Label_StatusChar.Caption := 'US'; $20: Label_StatusChar.Caption := '半角スペース'; $7F: Label_StatusChar.Caption := 'DEL'; $3000: Label_StatusChar.Caption := '全角スペース'; else Label_StatusChar.Caption := ls_Str; end; if (li_Code < $20) or (li_Code = $7F) then begin Label_StatusChar.Color := clAqua; end else begin Label_StatusChar.ParentColor := True; end; if (gfnbIsUnicode(ls_Str)) then begin Label_StatusAnsi.Caption := 'SJIS -'; end else begin ls_SJis := WideString(ls_Str); if (Length(ls_SJis) > 1) then begin //2バイト文字 Label_StatusAnsi.Caption := Format('SJIS 0x%.2x%.2x', [Ord(ls_SJis[1]), Ord(ls_SJis[2])]); end else if (ls_SJis <> '') then begin //1バイト文字 Label_StatusAnsi.Caption := Format('SJIS 0x%.2x', [Ord(ls_SJis[1])]); end else begin //空文字 Label_StatusAnsi.Caption := ''; end; end; end; end; procedure TApp_TOOLLFont.FormCreate(Sender: TObject); begin {$IFDEF DEBUG} myDebug.gpcMessageModeSet(True); {$ENDIF} Self.Icon := Application.Icon; Memo_Text.Align := alClient; Memo_Text.AutoFont := True; //ステータスバー、情報表示用 Label_StatusChar.Caption := ''; Label_StatusAnsi.Caption := ''; Label_StatusUnicode.Caption := ''; Label_StatusUtf8.Caption := ''; FLoadIni; //クリップボード監視 FEntryClipboardViewer; Tag := 1; Show; // Memo_Text.SetFocus; if (Memo_Text.Text <> '') then begin Memo_TextSelectionChange(nil); end; gpcFormBringToFront(Self); end; procedure TApp_TOOLLFont.FormDestroy(Sender: TObject); //終了処理 begin Tag := 0; Hide; //クリップボード監視を解除 FRemoveClipboardViewer; FSaveIni; end; //終了 procedure TApp_TOOLLFont.Action_FileExitExecute(Sender: TObject); begin Close; end; // 編集 ------------------------------------------------------------------------ //状況に応じたメニューの変更 procedure TApp_TOOLLFont.PopupMenu_MainPopup(Sender: TObject); begin Action_EditUndo.Enabled := Memo_Text.CanUndo; Action_EditRedo.Enabled := Memo_Text.CanRedo; Action_EditCut.Enabled := Memo_Text.Selected; Action_EditDelete.Enabled := Action_EditCut.Enabled; // Action_EditPaste.Enabled := (gfnsStrFromClipboard <> ''); Action_EditPaste.Enabled := Clipboard.HasFormat(CF_TEXT); Action_TextReplace.Enabled := Action_EditPaste.Enabled; //すべて選択 Action_EditSelectAll.Enabled := (Memo_Text.Text <> ''); //コピー Action_EditCopy.Enabled := Memo_Text.Selected; end; //元に戻す procedure TApp_TOOLLFont.Action_EditUndoExecute(Sender: TObject); begin Memo_Text.Undo; end; //やり直し procedure TApp_TOOLLFont.Action_EditRedoExecute(Sender: TObject); begin Memo_Text.Redo; end; //切り取り procedure TApp_TOOLLFont.Action_EditCutExecute(Sender: TObject); begin FsCopyText := Memo_Text.StrCopy; Memo_Text.CutToClipboard; end; //コピー procedure TApp_TOOLLFont.Action_EditCopyExecute(Sender: TObject); begin FsCopyText := Memo_Text.StrCopy; Memo_Text.CopyToClipboard; end; //貼り付け procedure TApp_TOOLLFont.Action_EditPasteExecute(Sender: TObject); begin Memo_Text.PasteFromClipboard; end; //削除 procedure TApp_TOOLLFont.Action_EditDeleteExecute(Sender: TObject); begin Memo_Text.ClearSelection; end; //全て選択 procedure TApp_TOOLLFont.Action_EditSelectAllExecute(Sender: TObject); begin Memo_Text.SelectAll; end; procedure TApp_TOOLLFont.Action_TextReplaceExecute(Sender: TObject); //テキスト置き換え var ls_Str : WideString; begin ls_Str := gfnsStrFromClipboard; { myDebug.gpcDebug([ls_Str, FsCopyText, ls_Str = FsCopyText]); if (ls_Str <> FsCopyText) then begin myDebug.gpcDebug([Length(ls_Str), Length(FsCopyText)]); myDebug.gpcDebugDump(PAnsiChar(PWideChar(ls_Str)), Length(ls_Str) * 2); myDebug.gpcDebugDump(PAnsiChar(PWideChar(FsCopyText)), Length(FsCopyText) * 2); end; } if (ls_Str <> '') and (ls_Str <> Memo_Text.Text) and (ls_Str <> FsCopyText) then begin //ClearしたりTextに文字列をセットするとUndoが効かなくなる // Memo_Text.Clear; // Memo_Text.Text := ls_Str; // Memo_Text.Text := Clipboard.AsText + #13 + gfnsStrFromClipboard; Memo_Text.SelectAll; Memo_Text.ClearSelection; Memo_Text.PasteFromClipboard; Memo_Text.SelStart := 0; Memo_TextSelectionChange(nil); end; FsCopyText := ''; end; procedure TApp_TOOLLFont.Action_TextClearExecute(Sender: TObject); //テキストクリア begin Memo_Text.Clear; PopupMenu_MainPopup(nil); Memo_TextSelectionChange(nil); end; procedure TApp_TOOLLFont.Action_TextWrapExecute(Sender: TObject); begin Memo_Text.WordWrap := Action_TextWrap.Checked; end; procedure TApp_TOOLLFont.__mniPEdit_TabClick(Sender: TObject); //Tabの入力 begin Memo_Text.Insert(#9); end; procedure TApp_TOOLLFont.Action_FontSelExecute(Sender: TObject); //フォント選択 begin FontDialog1.Font := Memo_Text.Font; if (Sender = nil) or (FontDialog1.Execute) then begin Memo_Text.Font := FontDialog1.Font; end; end; procedure TApp_TOOLLFont.Action_HelpVersionInfoExecute(Sender: TObject); //ヘルプ begin gpcVersionInfoCreate; gpcVersionInfoURLSet('http://drang.s4.xrea.com/program/tool/epad/lfont/help/'); gpcVersionInfoShowModal; gpcVersionInfoRelease; end; procedure TApp_TOOLLFont.actNop(Sender: TObject); begin // end; //------------------------------------------------------------------------------ //設定ファイル const // lcsSECT_BOUNDS = 'Bounds'; lcsSECT_TEXTHISTORY = 'TextHistory'; lcsSECT_TEXT = 'Text'; lcsKEY_TEXTCHECK = 'CheckClipboard'; lcsKEY_TEXTWRAP = 'WordWarp'; lcsKEY_TEXTFONT = 'Font'; //設定読み込み procedure TApp_TOOLLFont.FLoadIni; var l_IniFile : TMyIniFile; begin if not(gfnbKeyStateAnd([VK_SHIFT, VK_CONTROL])) then begin l_IniFile := TMyIniFile.Create; try with l_IniFile do begin //[Bounds] SetMonitorBoundsRect(Self); //[Text] Action_TextCheckClipboard.Checked := ReadBool(lcsSECT_TEXT, lcsKEY_TEXTCHECK, Action_TextCheckClipboard.Checked); Action_TextWrap.Checked := ReadBool(lcsSECT_TEXT, lcsKEY_TEXTWRAP, Action_TextWrap.Checked); SetFont(lcsSECT_TEXT, lcsKEY_TEXTFONT, FontDialog1.Font); end; finally l_IniFile.Free; end; end; Action_TextWrapExecute(nil); Action_FontSelExecute(nil); end; //設定保存 procedure TApp_TOOLLFont.FSaveIni; var l_IniFile : TMyIniFile; begin if (gfnbKeyStateAnd([VK_SHIFT, VK_CONTROL])) then begin Exit; end; l_IniFile := TMyIniFile.Create; try with l_IniFile do begin //[Bounds] WriteBoundsRect(Self); //[Text] WriteBool(lcsSECT_TEXT, lcsKEY_TEXTCHECK, Action_TextCheckClipboard.Checked); WriteBool(lcsSECT_TEXT, lcsKEY_TEXTWRAP, Action_TextWrap.Checked); WriteFont(lcsSECT_TEXT, lcsKEY_TEXTFONT, Memo_Text.Font); end; finally l_IniFile.Free; end; end; end.