home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Softwarová Záchrana 3
/
Softwarova-zachrana-3.bin
/
ArsClip
/
source.zip
/
UnitFrmMainPopup.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
2004-11-09
|
67KB
|
2,171 lines
unit UnitFrmMainPopup;
{
This unit displays the main popup menu when a hotkey is pressed
UnitFrmConfig is responsible for setting/releasing the hotkey -
I had a good reason why, but I don't remeber it. I think there
was a circular reference where each form required the other during
creation.
NOTE:
Ignore the clipboard from Hotkey until Popup Dismissal
Ignore the clipboard from paste start until paste end
Inform the FrmClipboardManager any time we paste an item.
(in routines SendText and OtherItemClickEvent)
Update:
Fix to detect accidental single/double click on System Tray Icon to show popup
Show "Paste as Plain Text" when pasting as Complex Item by default
----------------------
Mouse Position always used no matter the configuration
Problem pasting from ArsClip into ArsClip
---------------------
"All Items..." support
Default mouse position when carat not found - Mozilla tweak
--------------------
Fixed duplicate hotkey detection to work with the Tooltip Popup hotkeys
--------------------
Changed to allow ArsClip to paste into its own windows, like
Permanent Items. (Relies on new 'place on clipboard' method
ArsClip uses)
--------------------
Duplicate Hotkey message detection
Optional paste as Complex Item
--------------------
"Current:" item for text & nontext items
Updates to paste Permanent Items with embeded keystrokes
--------------------
New CTRL+Click option for Rich Text - only shown when rich text
found associated to a text clip.
Updated for option to show popup on double-click
Save Removed Items on Close.....
Handle Tooltip hotkeys
Tooltips for
------
New Form Mode / Next Field buttons
Number 1 - 9, 0, A-Z on popup
--
Ignore the Hotkey while the Popup is being displayed.
New secondary popup menu for text items (alternative to
function key + clicking on items)
Updated the focus rules for asking the user about "no-paste" windows
in the hotkey message method.
s
--
New SHIFT+INSERT pasting method
Shift + Click to preview a picture (non-text item)
F1 + Click to copy to clipboard only a non-text item
Non-text items shown in Newest-To-Oldest order
Flush non-text items command in Full Mode
Flush text items command in Full Mode
--
Show configured (either on popup or in submenu) for
permanent item groups in full mode - default to on popup when not
specified
New F1+Click to copy to clipboard only
New F2+Click to make into a new Permanent Item
Cleaned up special Key+Click code
New 'Full Mode/Configured Mode' toggle.
Code cleanup - made SendCTRL_V procedure.
Allow user to specify "NoPaste" for programs that don't
have a target control.
New option for quick-change of Permanent Item groups
CTRL+Clicks on Menu Items, Last, Current, Permanent Items will open
files, urls, folders, etc.
Using UnitClipQueue
New handling for tabs in the display of clip items
Focus is now returned when ESC is pressed
}
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Clipbrd, Menus, StrUtils, ShellAPI, ExtCtrls, Buttons,
IniFiles {for hashed}, UnitTooltipPopup,
UnitMyPopup, UnitClipQueue, UnitTWideChar;
type
TFrmMainPopup = class(TForm)
Memo1: TMemo;
btnHide: TButton;
imgA: TImage;
imgRightArrow: TImage;
imgIcon: TImage;
imgFull: TImage;
pmItemOptions: TPopupMenu;
Run1: TMenuItem;
MakePermanentItem1: TMenuItem;
PasteusingMimicTyping1: TMenuItem;
Placeonclipboard1: TMenuItem;
Preview1: TMenuItem;
back1: TMenuItem;
Cancel1: TMenuItem;
N2: TMenuItem;
PasteusingSHIFTINS1: TMenuItem;
N1: TMenuItem;
PasteusingCTRLV1: TMenuItem;
imgPasteAll: TImage;
imgPaste: TImage;
imgEdit: TImage;
imgFlush: TImage;
imgConfMode: TImage;
imgPermCasc: TImage;
imgRemoved: TImage;
N0PasteasRichText1: TMenuItem;
tim: TTimer;
AMakePermanentas1: TMenuItem;
N3: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure btnHideClick(Sender: TObject);
procedure Run1Click(Sender: TObject);
procedure MakePermanentItem1Click(Sender: TObject);
procedure PasteusingMimicTyping1Click(Sender: TObject);
procedure Placeonclipboard1Click(Sender: TObject);
procedure Preview1Click(Sender: TObject);
procedure back1Click(Sender: TObject);
procedure PasteusingSHIFTINS1Click(Sender: TObject);
procedure PasteusingCTRLV1Click(Sender: TObject);
procedure N0PasteasRichText1Click(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure AMakePermanentas1Click(Sender: TObject);
procedure MimicTyping1Click(Sender: TObject);
procedure N2SHIFTINSERT1Click(Sender: TObject);
procedure N3CTRLV1Click(Sender: TObject);
procedure N4ClipboardOnly1Click(Sender: TObject);
procedure N5Default1Click(Sender: TObject);
//procedure timTimer(Sender: TObject);
private
{ Private declarations }
HotKeyForeWindow: cardinal; {target window for text pasting}
HotKeyTarget: cardinal; {target control with keyboard focus}
TargetEXE : string; {name of program that created window}
TargetX, TargetY : integer;
Popup: TMyPopupMenu; {text pasting popup}
PopupShowing : boolean;
LastStringSelected : string; {last selected queue item from Popup}
MenuItemText : string;
CurrentClipboard : TClipItem;
CTRLClickedItem : TClipItem;
ThreadOurs : cardinal; {Used soley by ThreadAttach/Detach}
ThreadTarget : cardinal;
ThreadAttached : boolean;
{configuration options}
PopupUseKB : boolean;
VisibleCharCount : longint;
UsePermanentItems : boolean;
DoShowEditHistory : boolean;
DoShowPasteAll : boolean;
DoMoveSelectedToTop : boolean;
DoShowCurrentItem : boolean;
DoShowPermanentItemGroups : boolean;
DoShowPermanentItemSubmenu : boolean;
DoRememberHistory : boolean;
DoShowLast : boolean;
DoShowFormMode : boolean;
IgnoreHotkey : boolean;
{UsePermanentItemsMore : boolean;
PermanentItemsToShow : integer;}
PermanentItemsCurrentTop : integer;
{keystrokes monitored when an item is clicked}
CopyKey : integer;
PermanentKey : integer;
MimicKey : integer;
{non-text items}
UseOtherClipboardOnly : boolean;
UseOtherPasting : boolean;
UseFormMode : boolean;
UseCtrlClickOpen, UseCtrlClickMenu : boolean;
FullMode : boolean; // user pressed Full Mode command
//NoPastePrograms : THashedStringList; // List of programs that ArsClip will use
// clipboard only mode.
TooltipPopup : TTooltipPopup;
HotkeyActive : boolean;
PopupActive : boolean;
{unicode poup}
procedure HandleCloseEvent;
procedure HandleFormMode;
function ThreadAttach(TargetWindow: cardinal) : boolean;
procedure ThreadDetach();
procedure GatherTargetWindowData;
procedure GetTargetControl(ParentWindow: cardinal;
var TargetHandle: cardinal;
var TargetX: integer;
var TargetY: integer);
{
// possible future use
procedure MyOnDraw(Sender: TObject; ACanvas: TCanvas;
ARect: TRect; Selected: Boolean);
procedure MyOnMeasure(Sender: TObject; ACanvas: TCanvas;
var Width, Height: Integer);
}
procedure ShowPopupWithFocusRules;
procedure ShowPopup(X,Y: integer);
//
// util functions
//
procedure ShowPreviewForm;
function KeyPressedOverride(s : string; ci : TClipItem = nil) : boolean;
protected
public
{public declarations}
procedure SendText(s : string; ci : TClipItem = nil);
procedure ShowOnNextWindow(ShowPopup : boolean = true);
function GetNextWindowProgramName : string;
{configuration}
procedure SetPopupUseKeyboard(usekb: boolean);
procedure SetVisibleCharacterCount(count: longint);
procedure SetPermanentItems(DoUse: boolean);
procedure SetShowPermeanentItemGroups(enable : boolean);
procedure SetShowPermanentItemSubmenu(value : boolean);
procedure SetOtherPasteMethodPasting();
procedure SetOtherPasteMethodClipboardOnly();
procedure SetShowEditHistory(value : boolean);
procedure SetShowPasteAll(DoShow: boolean);
procedure SetMoveSelectedItemToTop(DoMove : boolean);
procedure SetShowCurrentItem(DoShow: boolean);
procedure SetRememberHistory(DoRemember: boolean);
procedure SetDoShowLast(DoShow: boolean);
procedure SetShowFormMode(DoShow : boolean);
procedure SetCopyKey(key : integer);
procedure SetPermanentKey(key : integer);
procedure SetMimicKey(key : integer);
procedure SetCtrlClickOpen(value : boolean);
procedure SetCtrlClickMenu(value : boolean);
{these are shared with FrmDummyUnicodePopup}
//
// menu items selected on Popup window
//
function GetUsePermanentItems : boolean;
function GetDoShowEditHistory : boolean;
function GetDoShowPasteAll : boolean;
function GetDoMoveSelectedToTop : boolean;
function GetDoShowCurrentItem : boolean;
function GetDoShowPermanentItemGroups : boolean;
function GetDoShowPermanentItemSubmenu : boolean;
function GetDoRememberHistory : boolean;
function GetDoShowLast : boolean;
function GetDoShowFormMode : boolean;
function GetLastStringSelected : string;
function GetUseFormMode : boolean;
function GetFullMode : boolean;
function GetAccelerator(i: integer): char;
function GetTrimmedItem(item : string) : string;
procedure MenuItemClickEvent(Sender: TObject);
procedure FlushTextItemsClickEvent(Sender: TObject);
procedure EditHistoryItemClickEvent(Sender : TObject);
procedure OtherItemClickEvent(Sender: TObject);
procedure FlushOtherItemsClickEvent(Sender: TObject);
procedure LastMenuItemClickEvent(Sender: TObject);
procedure CancelMenuItemClickEvent(Sender: TObject);
procedure PermanentMenuItemClickEvent(sender: TObject); overload;
procedure PermanentMenuItemClickEvent(s : string); overload;
procedure PermanentGroupItemClickEvent(sender: TObject); overload;
procedure PermanentGroupItemClickEvent(s : string); overload;
procedure PasteAllMenuItemClickEvent(sender: TObject);
procedure PasteSelectedMenuItemClickEvent(sender: TOBject);
procedure CurrentMenuItemClickEvent(Sender: TObject);
procedure FullModeMenuItemClickEvent(Sender : TObject);
procedure FormModeMenuItemClickEvent(Sender : TObject);
procedure NextFieldModeMenuItemClickEvent(Sender : TObject);
{system tray stuff/ windows messages}
procedure WMHotKey(var Msg : TWMHotKey); message WM_HOTKEY;
procedure WMEndSession(var msg : TWMQueryEndSession); message WM_QUERYENDSESSION;
procedure AppendLog(s : string);
procedure ShowOnSystemTray;
end;
var
FrmMainPopup: TFrmMainPopup;
implementation
uses UnitFrmConfig, UnitFrmClipboardManager,
UnitFrmPasteSelected, UnitOtherQueue, UnitKeyboardQuery,
TLHelp32, UnitFrmPreview, UnitFrmPermanentNew,
UnitFrmRemoved, UnitFrmSysTrayMenu, UnitPaste, UnitMisc, Math,
CommCtrl, UnitFrmDummyUnicodeTooltip, UnitfrmDummyUnicodePopup ;
CONST PASTE_ONLY_FILE : string = 'nopaste.txt';
{$R *.dfm}
{
--========================
-- // Public Interface //
--========================
}
procedure TFrmMainPopup.SetShowFormMode(DoShow : boolean);
begin
self.DoShowFormMode := DoShow;
end;
procedure TFrmMainPopup.SetCtrlClickOpen(value : boolean);
begin
self.UseCtrlClickOpen := value;
self.UseCtrlClickMenu := not value;
end;
procedure TFrmMainPopup.SetCtrlClickMenu(value : boolean);
begin
self.UseCtrlClickOpen := not value;
self.UseCtrlClickMenu := value;
end;
procedure TFrmMainPopup.SetMimicKey(key : integer);
begin
self.MimicKey := VK_F1 + key;
end;
procedure TFrmMainPopup.SetCopyKey(key : integer);
begin
self.CopyKey := VK_F1 + key;
end;
procedure TFrmMainPopup.SetPermanentKey(key : integer);
begin
self.PermanentKey := VK_F1 + key;
end;
procedure TFrmMainPopup.SetShowEditHistory(value : boolean);
begin
self.DoShowEditHistory := value;
end;
procedure TFrmMainPopup.SetShowPermanentItemSubmenu(value : boolean);
begin
if (value) then begin
DoShowPermanentItemSubmenu := true;
DoShowPermanentItemGroups := false;
end;
end;
procedure TFrmMainPopup.SetShowPermeanentItemGroups(enable : boolean);
begin
if (enable) then begin
DoShowPermanentItemSubmenu := false;
DoShowPermanentItemGroups := true;
end;
end;
procedure TFrmMainPopup.SetOtherPasteMethodPasting();
begin
self.UseOtherClipboardOnly := false;
self.UseOtherPasting := true;
end;
procedure TFrmMainPopup.SetOtherPasteMethodClipboardOnly();
begin
self.UseOtherClipboardOnly := true;
self.UseOtherPasting := false;
end;
procedure TFrmMainPopup.SetDoShowLast(DoShow: boolean);
begin
self.DoShowLast := DoShow;
end;
procedure TFrmMainPopup.SetRememberHistory(DoRemember: boolean);
begin
self.DoRememberHistory := DoRemember;
end;
procedure TFrmMainPopup.SetVisibleCharacterCount(count: longint);
begin
self.VisibleCharCount := count;
end;
procedure TFrmMainPopup.SetShowCurrentItem(DoShow: boolean);
begin
self.DoShowCurrentItem := doshow;
end;
procedure TFrmMainPopup.SetShowPasteAll(DoShow: boolean);
begin
self.DoShowPasteAll := DoShow;
end;
procedure TFrmMainPopup.SetPopupUseKeyboard(usekb: boolean);
begin
self.PopupUseKB := usekb;
end;
procedure TFrmMainPopup.SetPermanentItems(DoUse: boolean);
begin
self.UsePermanentItems := douse;
end;
procedure TFrmMainPopup.SetMoveSelectedItemToTop(DoMove : boolean);
begin
DoMoveSelectedToTop := DoMove;
end;
{
--========================
-- // Create/Destroy //
--========================
Popup menu
NoPaste file
Init vars
Handle a form close or a logoff/shutdown
}
procedure TFrmMainPopup.FormCreate(Sender: TObject);
begin
//
// popup & menu items init
//
self.ShowHint := true;
Popup := TMyPopupMenu.Create(self);
TooltipPopup := TTooltipPopup.Create;
ThreadAttached := false;
{
NoPastePrograms := THashedStringList.Create;
f := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName)) +
PASTE_ONLY_FILE;
If FileExists(f) then begin
NoPastePrograms.LoadFromFile(f);
end;
}
self.CurrentClipboard := TClipItem.Create;
end;
procedure TFrmMainPopup.FormClose(Sender: TObject; var Action: TCloseAction);
begin
self.HandleCloseEvent;
end;
//
// When OS is shutting down/logging off
//
procedure TFrmMainPopup.WMEndSession(var msg : TWMQueryEndSession);
begin
self.HandleCloseEvent;
msg.Result := 1; // do allow close
end;
procedure TFrmMainPopup.HandleCloseEvent;
begin
if self.DoRememberHistory then begin
frmClipboardManager.SaveHistory;
//frmRemoved.SaveHistory;
end;
{
if NoPastePrograms.Count > 0 then begin
f := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName)) +
PASTE_ONLY_FILE;
NoPastePrograms.SaveToFile(f);
end;
}
FrmConfig.SaveLastPermPath;
FrmPermanent.Close;
//
// clean up resources
//
//MyFree(NoPastePrograms);
Popup.Items.Clear;
MyFree(Popup);
MyFree(Self.CurrentClipboard);
end;
{
--======================
-- // HotKey Message //
--======================
Description:
Find the target control
- Handle case when no target control
- allow user to add problematic program to "No Paste" list
Finally, pass control to ShowPopupWithFocusRules
info collected here:
HotKeyForeWindow
HotKeyTarget
TargetX
TargetY
TargetEXE
}
procedure TFrmMainPopup.WMHotKey(var Msg: TWMHotKey);
label EXIT_CODE;
begin
// Duplicate message detection
Windows.SetLastError(ERROR_SUCCESS);
if (self.HotkeyActive) then begin
UnitMisc.AppendLog('Duplicate hotkey press detected');
EXIT;
end;
self.HotkeyActive := true;
// Ignore any hotkeys that don't belong to us
if (msg.HotKey <> FrmConfig.GetHotKeyID) and
(msg.HotKey <> FrmCOnfig.GetTTHotKeyID)and
(msg.HotKey <> FrmCOnfig.GetPTTHotKeyID)
then begin
goto EXIT_CODE;
end;
if self.ThreadAttached then begin
sleep(100);
if self.ThreadAttached then begin
UnitMisc.AppendLog('wm_hotkey - thread already attached');
goto EXIT_CODE;
end;
end;
// Ignore the clipboard as soon as the hotkey is pressed
// Stop ignoring on an error exit
// Each invididual menu item is responsible to stop ingoring the clipboard
//frmClipboardManager.SetIgnoreClipboard(true);
UnitMisc.AppendLog('WM_Hotkey - received');
if (self.IgnoreHotkey) then begin
UnitMisc.AppendLog('ignoring hotkey');
//frmClipboardManager.SetIgnoreClipboard(false);
goto EXIT_CODE;
end;
// get current foreground window
// get the data needed to show the popup from the window
self.HotKeyForeWindow := Windows.GetForegroundWindow();
if (self.HotKeyForeWindow = 0) then begin
ShowMessage('Couldn''t get foreground window');
//frmClipboardManager.SetIgnoreClipboard(false);
goto EXIT_CODE;
end;
self.GatherTargetWindowData;
// Show the Popup, Next Tooltip, or Previous Toolip
if (msg.HotKey = FrmConfig.GetHotKeyID) then begin
self.FullMode := false;
self.ShowPopupWithFocusRules;
end else if (msg.HotKey = FrmConfig.GetTTHotKeyID) then begin
self.HotkeyActive := false;
TooltipPopup.ShowTooltipNext(targetx + 10, targety+20);
end else if (msg.HotKey = FrmConfig.GetPTTHotKeyID) then begin
self.HotkeyActive := false;
TooltipPopup.ShowTooltipPrev(targetx + 10, targety+20);
end;
EXIT_CODE:
self.HotkeyActive := false;
end;
procedure TFrmMainPopup.GatherTargetWindowData;
var answer : longint;
begin
Windows.SetLastError(ERROR_SUCCESS);
// find control with focus on foreground window
// ingore error when pasting option is "Clipboard Only"
self.GetTargetControl(self.HotKeyForeWindow, self.HotKeyTarget,
TargetX, TargetY);
if (FrmConfig.cbDisplayAtMouseCursor.Checked) then begin
TargetX := Mouse.CursorPos.X;
TargetY := Mouse.CursorPos.Y;
end;
self.TargetEXE := WindowHandleToEXEName(self.HotKeyForeWindow);
Paste.ClearOnceFlags;
case Paste.GetPasteMethod(self.TargetEXE) of
PASTE_CTRL_V :
begin
Paste.SetUsePasteCVOnce;
end;
PASTE_SHIFT_INS :
begin
Paste.SetUsePasteSIOnce;
end;
PASTE_MIMIC :
begin
Paste.SetKeyboardMimicOnce;
end;
PASTE_CLIPBOARD :
begin
Paste.SetClipboardOnlyOnce;
end;
PASTE_DEFAULT :
begin
end;
end;
//
// Default to mouse position when can't target a control
//
if (HotKeyTarget = 0) then begin
{
Windows.GetWindowPlacement(self.HotKeyForeWindow, @wp);
TargetX := wp.rcNormalPosition.Left;
TargetY := wp.rcNormalPosition.Top;
}
TargetX := Mouse.CursorPos.X;
TargetY := Mouse.CursorPos.Y;
//
// Bitch if were not in ClipboardOnly mode
// or per-program override can't paste the item right by default.
// Allow user to always use ClipboardOnly for the problematic
// program
// [Answer Yes = add EXE name to NoPaste file]
//
if (not (Paste.GetPasteMethod(self.TargetEXE) in [PASTE_CLIPBOARD, PASTE_MIMIC]))
and
(not (Paste.GetDefaultPasteMethod in [PASTE_CLIPBOARD, PASTE_MIMIC]))
then begin
Windows.SetForegroundWindow(self.Handle);
answer := MessageDlg('Coudn''t find control to target in program ' + uppercase(self.TargetEXE) + #13#10
+ 'Would you like to use "Copy to clipboard only" for this program?',
mtConfirmation, [mbyes, mbno],0 );
if (answer = mryes) then begin
//NoPastePrograms.Add(self.TargetEXE);
Paste.AssignPaste(self.TargetEXE, PASTE_CLIPBOARD);
end;
if (answer <> mryes) then begin
Windows.SetForegroundWindow(self.HotKeyForeWindow);
//frmClipboardManager.SetIgnoreClipboard(false);
EXIT;
end;
//Paste.SetClipboardOnlyOnce;
end;
Windows.SetForegroundWindow(self.Handle);
end;
end;
procedure TfrmMainPopup.GetTargetControl(ParentWindow: cardinal;
var TargetHandle: cardinal;
var TargetX: integer;
var TargetY: integer);
var CaretPos: TPoint;
Rect: TRect;
begin
Windows.SetLastError(ERROR_SUCCESS);
// attempt to get target control's handle and
// the position of the caret in the text window
//
TargetHandle := 0;
if (self.ThreadAttach(ParentWindow)) then begin
TargetHandle := Windows.GetFocus();
if (TargetHandle <> 0) then begin
Windows.GetCaretPos(CaretPos);
Windows.GetWindowRect(HotKeyTarget, Rect);
TargetX := Rect.left + CaretPos.X;
TargetY := Rect.top + CaretPos.Y;
end;
self.ThreadDetach;
end;
end;
//
// ShowPopupWithFocusRules: Wrapper function to call ShowPopup enforcing the
// focus rules. The rule is to return focus to the original window.
//
// Once the Hotkey has been pressed, you can reshow the
// popup again by calling this procedure.
//
// Program flow continues to a XXXClickEvent routine when the user
// selects an item from the popup window
procedure TFrmMainPopup.ShowPopupWithFocusRules;
begin
Windows.SetLastError(ERROR_SUCCESS);
// Attaching to the target keeps the popup from
// taking away focus from the target item.
// Example, pasting to the name of a desktop icon. If you remove
// focus, you remove the rename box
if (self.PopupUseKB) then begin
// we need to be foreground for keyboard focus
Windows.SetForegroundWindow(self.Handle);
self.ShowPopup(TargetX, TargetY);
// make sure focus is returned
if (self.ThreadAttach(self.HotKeyForeWindow)) then begin
SetForegroundWindow(self.HotKeyForeWindow);
self.ThreadDetach;
end;
end else begin
if (not self.ThreadAttach(self.HotKeyForeWindow)) then begin
ShowMessage('ERROR: Couldn''t attach popup menu to this window');
//frmClipboardManager.SetIgnoreClipboard(false);
exit;
end;
self.ShowPopup(TargetX, TargetY);
self.ThreadDetach();
end;
end;
procedure TfrmMainPopup.ShowPopup(X,Y: integer);
procedure DrawIconOnMenuItem(m : TMenuItem; icon : HICON);
begin
if (icon <> 0) then begin
//DrawIcon(imgIcon.Canvas.Handle,0,0,icon);
m.bitmap.width := 32;
m.bitmap.height := 32;
m.bitmap.pixelformat := pf24bit;
if not DrawIcon(m.Bitmap.Canvas.Handle,0,0,icon) then begin
UnitMisc.AppendLog('DrawIcon failed:' + SysUtils.SysErrorMessage(getlasterror) );
end;
end;
end;
procedure PopulatePopupANSI;
var i, j : integer;
m, subm, subm2 : TMenuItem;
s : string;
icon : HICON;
ci : TClipItem;
begin
//
// Recreate the menuitems
//
popup.Items.Clear;
for i := 0 to (ClipQueue.GetQueueCount - 1) do begin
m := TMenuItem.Create(popup);
s := ClipQueue.GetItemText(i);
if (self.PopupUseKB) then begin
m.Caption := '&' + GetAccelerator(i) + ': ' + GetTrimmedItem(s);
end else begin
m.Caption := GetTrimmedItem(s);
end;
m.hint := s;
ci := ClipQueue.GetClipItem(i);
icon := 0;
if ci <> nil then begin
icon := ci.CData.GetHICON;
if (FrmConfig.cbShowTypes.Checked) then begin
m.caption := UnitMisc.GetCliptypeSymbol(ci.GetFormat) + ' ' + m.Caption;
end;
end;
DrawIconOnMenuItem(m, icon);
m.OnClick := self.MenuItemClickEvent;
popup.Items.Add(M);
end;
{
if (self.FullMode) then begin
m := TMenuItem.Create(Popup);
m.Caption := 'Flush Text';
m.OnClick := self.FlushTextItemsClickEvent;
m.Bitmap := imgFlush.Picture.Bitmap;
popup.Items.Add(m);
end;
}
if (self.DoShowEditHistory) or (self.FullMode) then begin
m := TMenuItem.Create(Popup);
m.Caption := 'Edit History...';
m.OnClick := self.EditHistoryItemClickEvent;
m.Bitmap := imgEdit.Picture.Bitmap;
popup.Items.Add(m);
end;
//
// other clipboard items
// The hint contains the items index in the queue
//
if (OtherQueue.GetQueueCount > 0) then begin
popup.Items.Add(NewLine());
for i := (OtherQueue.GetQueueCount - 1) downto 0 do begin
m := TMenuItem.Create(popup);
m.Caption := OtherQueue.GetClipItem(i).GetAsText + ': size ' +
IntToStr(Trunc(OtherQueue.GetClipItem(i).GetDataSize / 1024)) +
' KB';
//m.Hint := IntToStr(i);
m.ImageIndex := i;
DrawIconOnMenuItem(m, OtherQueue.GetClipItem(i).CData.GetHICON);
m.OnClick := OtherItemClickEvent;
popup.items.Add(m);
end;
{
if (self.FullMode) then begin
m := TMenuItem.Create(popup);
m.Caption := 'Flush non-text';
m.OnClick := FlushOtherItemsClickEvent;
m.Bitmap := imgFlush.Picture.Bitmap;
popup.Items.Add(m);
end;
}
end;
//
// divider line cancel cancel
// divider line Last string option
//
popup.Items.Add(NewLine());
m := TMenuItem.Create(popup);
m.caption := 'Cancel';
m.OnClick := self.CancelMenuItemClickEvent;
popup.Items.Add(m);
if ((self.DoShowLast) or (self.FullMode))and (trim(LastStringSelected) <> '') then begin
popup.Items.Add(Menus.NewLine());
m := TMenuItem.Create(popup);
m.caption := 'Last: ' + GetTrimmedItem(LastStringSelected);
m.OnClick := self.LastMenuItemClickEvent;
popup.Items.Add(m);
end;
// current clipboard item
// (may need to add line if 'Last' doesn't exist yet)
if (self.DoShowCurrentItem) or (self.FullMode) then begin
if (trim(LastStringSelected) = '') or (not (self.DoShowLast or FullMode)) then begin
popup.Items.Add(Menus.NewLine());
end;
m := TMenuItem.Create(popup);
self.CurrentClipboard.GetClipboardItem(0);
if (self.CurrentClipboard.HasText) then begin
s := self.CurrentClipboard.GetAsText;
end else begin
s := self.CurrentClipboard.GetFormatName;
end;
m.Hint := s;
if (s = '') then begin
m.Caption := GetTrimmedItem('Current: ' +self.CurrentClipboard.GetFormatName);
end else begin
m.caption := GetTrimmedItem('Current: ' + self.CurrentClipboard.GetAsText);
end;
m.OnClick := self.CurrentMenuItemClickEvent;
popup.Items.Add(m);
end;
//
// paste all / paste selected
//
if (self.DoShowPasteAll) or (self.FullMode)
or (self.DoShowFormMode) or (self.UseFormMode) then begin
popup.Items.Add(menus.NewLine());
if (self.DoShowPasteAll) or (self.FullMode) then begin
m := TMenuItem.Create(popup);
m.caption := 'Paste All';
m.OnClick := self.PasteAllMenuItemClickEvent;
m.Bitmap := self.imgPasteAll.Picture.Bitmap;
popup.Items.Add(m);
m := TMenuItem.Create(popup);
m.caption := 'Paste Selected...';
m.OnClick := self.PasteSelectedMenuItemClickEvent;
m.Bitmap := self.imgPaste.Picture.Bitmap;
popup.Items.Add(m);
end;
if (self.DoShowFormMode) or (self.FullMode) or (self.UseFormMode) then begin
m := TMenuItem.Create(popup);
if self.UseFormMode then begin
m.caption := 'Form Mode OFF';
end else begin
m.caption := 'Form Mode ON';
end;
m.AutoCheck := true;
m.Checked := self.UseFormMode;
m.OnClick := self.FormModeMenuItemClickEvent;
m.Bitmap := self.imgEdit.Picture.Bitmap;
popup.Items.Add(m);
m := TMenuItem.Create(popup);
m.caption := '>> Next Field';
m.AutoCheck := true;
m.OnClick := self.NextFieldModeMenuItemClickEvent;
m.Bitmap := self.imgEdit.Picture.Bitmap;
popup.Items.Add(m);
end;
end;
//
// permanent items groups
//
if (self.UsePermanentItems) or (self.FullMode) then begin
{if not frmSysTrayMenu.GetJustSwitched then begin
FrmPermanent.AutoSwitch(self.TargetEXE);
end;}
popup.Items.Add(menus.NewLine());
for i := 0 to frmPermanent.GetCount - 1 do begin
m := TMenuItem.Create(popup);
m.hint := frmPermanent.GetItemText(i);
m.Caption := FrmPermanent.GetItemName(i);
m.OnClick := self.PermanentMenuItemClickEvent;
m.Tag := -1;
popup.Items.Add(m);
end;
//
// don't show in full mode if user specified submenu for Permanent
// Items
//
if (FrmConfig.cbShowSwitchTo.Checked or self.FullMode) then begin
if (self.DoShowPermanentItemGroups)
or (self.FullMode and (not self.DoShowPermanentItemSubmenu)) then begin
s := lowercase(frmPermanent.GetPermanentPath);
for i := 0 to frmPermanent.PermFoldersGetCount - 1 do begin
if (lowercase(frmPermanent.PermFoldersGetItem(i)) <> s) then begin
m := TMenuItem.Create(popup);
m.Hint := frmPermanent.PermFoldersGetItem(i);
m.Caption := 'Switch to ' + m.Hint;
m.OnClick := self.PermanentGroupItemClickEvent;
m.Bitmap := imgRightArrow.Picture.Bitmap;
popup.Items.Add(m);
end;
end;
end;
end;
//
// permanent items submenu
//
if (FrmConfig.cbShowSwitchTo.Checked or self.FullMode) then begin
if (self.DoShowPermanentItemSubmenu) then begin
subm := TMenuItem.Create(popup);
subm.Hint := '';
subm.Caption := 'Permanent Items...';
subm.Bitmap := imgPermCasc.Picture.Bitmap;
s := lowercase(frmPermanent.GetPermanentPath);
for i := 0 to frmPermanent.PermFoldersGetCount - 1 do begin
m := TMenuItem.Create(popup);
m.Hint := frmPermanent.PermFoldersGetItem(i);
if (lowercase(frmPermanent.PermFoldersGetItem(i)) <> s) then begin
m.Caption := 'Switch to ' + m.Hint;
end else begin
m.Caption := 'Switch to ' + m.Hint + ' (Current)';
end;
m.OnClick := self.PermanentGroupItemClickEvent;
subm.Add(m);
end;
popup.items.Add(subm);
end;
end;
// All Items as submenu
if (FrmConfig.cbShowAllItems.checked) or (self.fullmode) then begin
subm := TMenuItem.Create(popup);
subm.Hint := '';
subm.Caption := 'All Items...';
subm.Bitmap := imgPermCasc.Picture.Bitmap;
subm.OnClick := nil;
s := lowercase(frmPermanent.GetPermanentPath);
FrmPermanent.PermFolderPush;
for i := 0 to frmPermanent.PermFoldersGetCount - 1 do begin
if (lowercase(frmPermanent.PermFoldersGetItem(i)) <> s) then begin
m := TMenuItem.Create(popup);
m.Caption := frmPermanent.PermFoldersGetItem(i);
m.Hint := m.Caption;
FrmPermanent.SetPermanentPath(m.Hint);
for j := 0 to FrmPermanent.GetCount - 1 do begin
subm2 := TMenuItem.Create(popup);
subm2.Caption := FrmPermanent.GetItemName(j);
subm2.Hint := FrmPermanent.GetItemText(j);
subm2.tag := i;
subm2.OnClick := self.PermanentMenuItemClickEvent;
m.Add(subm2);
end;
m.OnClick := nil;
subm.Add(m);
end;
end;
FrmPermanent.PermFolderPop;
popup.items.Add(subm);
end;
end;
if (self.FullMode) then begin
m := TMenuItem.Create(popup);
m.Caption := 'System';
m.Hint := '';
m.Bitmap := self.imgPermCasc.Picture.Bitmap;
frmSysTrayMenu.ShowPopup(m);
m.OnClick := nil;
popup.Items.Add(m);
end;
//
// full mode/ configured mode
//
popup.Items.Add(menus.NewLine());
m := TMenuItem.Create(popup);
if (self.FullMode = true) then begin
m.Caption := 'Configured Mode';
m.Bitmap := self.imgConfMode.Picture.Bitmap;
end else begin
m.Caption := 'Full Mode';
m.Bitmap := self.imgFull.Picture.Bitmap;
end;
m.OnClick := self.FullModeMenuItemClickEvent;
m.Hint := '';
popup.Items.Add(m);
end;
begin
self.IgnoreHotkey := true;
if (self.PopupActive) then begin
EXIT;
end;
self.PopupActive := true;
if (self.PopupUseKB) then begin
popup.AutoHotkeys := maAutomatic;
end else begin
popup.AutoHotkeys := maManual;
end;
if not frmSysTrayMenu.GetJustSwitched then begin
FrmPermanent.AutoSwitch(self.TargetEXE);
end;
If (FrmConfig.cbDisplayUnicode.Checked) then begin
Popup.OwnerDraw := false;
PopulatePopupANSI;
FrmDummyUnicodePopup.ShowPopup(x,y, popup);
end else begin
Popup.OwnerDraw := false;
PopulatePopupANSI;
UnitMisc.AppendLog('Popup Activated');
popup.Popup(x, y);
UnitMisc.AppendLog('Popup End');
end;
//
// show
// NOTE: This code finishes before .SendText() is ever executed
// I need to stop ignoring here because the popup can be dismissed
// by ESC key or focus lost.
//frmClipboardManager.SetIgnoreClipboard(false);
self.IgnoreHotkey := false;
self.PopupActive := false;
end;
//
// create a 1..9/0 keys for items 0 to 9 and A to Z keys for items 10 and so no
//
function TFrmMainPopup.GetAccelerator(i: integer): char;
begin
case (i) of
0..8: result := chr(byte('1') + i);
9: result := '0';
else
result := chr(byte('A') + (i - 10));
end;
end;
// show a ' ...' when item is too long
// handle tabs and handle ampersans
function TFrmMainPopup.GetTrimmedItem(item : string) : string;
begin
result := item;
if (length(result) > VisibleCharCount) then begin
result := leftstr(item, VisibleCharCount) + '...';
end;
// tabs make the windows too damn long
// the #10 will make a funky box in the tab's place
result := stringreplace(result, #9,#10, [rfReplaceAll]);
result := stringreplace(result, #13,#10, [rfReplaceAll]);
result := stringreplace(result, '&', '&&', [rfReplaceAll]);
end;
procedure TFrmMainPopup.FormShow(Sender: TObject);
begin
UnitMisc.FlushLog;
end;
{
--============================
-- // Popup MenuItem Clicks //
--============================
Description:
Handle a normal menu item,
other item,
'cancel' item,
Last item,
Current item,
Paste All,
Paste Selected,
Permanent item
Text item make use of the SendText routing to enforce configuration
option.
Remember the last selected text item for the 'last' menu item option.
Inform the clipboard manager of any pasting we do.
}
//
// KeyPressedOverride
// Returns TRUE when an alternate action has taken place
// because of a KEYSTROKE+Click action by the user
// Returns FALSE when no override took place
//
function TFrmMainPopup.KeyPressedOverride(s : string; ci : TClipItem = nil) : boolean;
//
// run text as shell command
// or show CTRL+Click menu
//
function CTRLOpen(s : string) : boolean;
var i : integer;
begin
result := true;
// detect held CTRL key
// Execute item or show menu
if (KeyboardQuery.IsPressed(VK_CONTROL)) then begin
if (self.UseCtrlClickMenu) then begin
if (self.ThreadAttach(self.HotKeyForeWindow)) then begin
Windows.SetForegroundWindow(self.Handle);
self.ThreadDetach;
end;
for i := 0 to (pmItemOptions.Items.Count - 1) do begin
pmItemOptions.Items[i].Enabled := true;
end;
// Show the format in the "Paste as" Menu option
N0PasteasRichText1.Enabled := false;
N0PasteasRichText1.Caption := '&0 [no "paste as" format]';
AMakePermanentas1.Enabled := false;
AMakePermanentas1.Caption := '&A [no complex format]';
{
BAssignPasteMethodto1.Caption := '&B Assign Paste Method to '
+ self.TargetEXE;
}
self.CTRLClickedItem := ci;
if (self.CTRLClickedItem = nil) then begin
i := ClipQueue.IndexOf(s);
if (i <> -1) then begin
self.CTRLClickedItem := ClipQueue.GetClipItem(i);
end;
end;
if (self.CTRLClickedItem <> nil) then begin
if self.CTRLClickedItem.GetFormat = FrmClipboardManager.CF_RICHTEXT then begin
N0PasteasRichText1.Enabled := true;
if (FrmConfig.cbPasteComplex.Checked) then begin
N0PasteasRichText1.Caption := '&0 Paste as Plain Text';
end else begin
N0PasteasRichText1.Caption := '&0 Paste as Rich Text';
end;
AMakePermanentas1.Enabled := true;
AMakePermanentas1.Caption := '&A Make Permanent as Rich Text';
end;
if self.CTRLClickedItem.GetFormat = Windows.CF_UNICODETEXT then begin
pmItemOptions.Items[0].Enabled := true;
if (FrmConfig.cbPasteComplex.Checked) then begin
N0PasteasRichText1.Caption := '&0 Paste as Plain Text';
end else begin
N0PasteasRichText1.Caption := '&0 Paste as UNICODE';
end;
AMakePermanentas1.Enabled := true;
AMakePermanentas1.Caption := '&A Make Permanent as UNICODE';
end;
if (self.CTRLClickedItem.GetFormat = Windows.CF_HDROP) then begin
N0PasteasRichText1.Enabled := true;
N0PasteasRichText1.Caption := '&0 Paste as Files';
AMakePermanentas1.Enabled := true;
AMakePermanentas1.Caption := '&A Make Permanent as Files';
end;
if (self.CTRLClickedItem.GetFormat = FrmClipboardManager.CF_HTML) then begin
N0PasteasRichText1.Enabled := true;
N0PasteasRichText1.Caption := '&0 Paste as HTML';
AMakePermanentas1.Enabled := true;
AMakePermanentas1.Caption := '&A Make Permanent as HTML';
end;
end;
pmItemOptions.Items.RethinkHotkeys;
Run1.Caption := '&1 Run "'
+ self.GetTrimmedItem(s)
+ '..."';
pmItemOptions.Popup(self.TargetX, self.TargetY );
// make sure focus is returned
if (self.ThreadAttach(self.HotKeyForeWindow)) then begin
SetForegroundWindow(self.HotKeyForeWindow);
self.ThreadDetach;
end;
end else begin
//
// use the CTRL+Click Menu to do this
//
self.Run1.Click;
end;
EXIT;
end;
result := false;
end;
//
// Show a preview of item when SHIFT-Clicked
//
function SHIFTOpen(s : string) : boolean;
begin
result := true;
if (KeyboardQuery.IsPressed(VK_SHIFT)) then begin
self.Preview1.Click;
EXIT;
end;
result := false;
end;
function CopyKeyOpen(s : string) : boolean;
begin
//
// just turn on "Paste Only" toggle and let
// selected menu item handle sending the text as normal
//
if (KeyboardQuery.IsPressed(self.CopyKey)) then begin
Paste.SetClipboardOnlyOnce;
end;
result := false;
end;
function PermanentKeyOpen(s : string) : boolean;
begin
//
// Show Permanent Items dialog with new entry
//
result := true;
if (KeyboardQuery.IsPressed(Self.PermanentKey)) then begin
Windows.SetForegroundWindow(FrmPermanent.Handle);
frmPermanent.ShowWithNewItem(s);
EXIT;
end;
result := false;
end;
function MimicKeyOpen(s : string) : boolean;
begin
// just turn on "Mimic Typing" toggle and let
// selected menu item handle sending the text as normal
if (KeyboardQuery.IsPressed(self.MimicKey)) then begin
Paste.SetKeyboardMimicOnce;
end;
result := false;
end;
begin
result := CTRLOpen(s);
if (result) then EXIT;
result := SHIFTOpen(s);
if (result) then EXIT;
result := CopyKeyOpen(s);
if (result) then EXIT;
result := MimicKeyOpen(s);
if (result) then EXIT;
result := PermanentKeyOpen(s);
if (result) then EXIT;
end;
procedure TFrmMainPopup.ShowPreviewForm;
begin
Windows.SetForegroundWindow(FrmPreview.Handle);
FrmPreview.Left := Self.TargetX;
FrmPreview.Top := Self.TargetY;
FrmPreview.ShowModal;
self.ShowPopupWithFocusRules;
end;
procedure TfrmMainPopup.MenuItemClickEvent(Sender: TObject);
var s : string;
i : integer;
pasted : boolean;
begin
//
// The item is passed is a TMenuItem by default, but
// my hacked Unicode popup isn't that smart
//
if (Sender is TMenuItem) then begin
with Sender as TMenuItem do begin
s := Hint;
MenuItemText := s;
i := ClipQueue.IndexOf(s);
self.CTRLClickedItem := ClipQueue.GetClipItem(i);
end;
end else begin
self.CTRLClickedItem := TClipItem(sender);
s := self.CTRLClickedItem.GetAsText;
MenuItemText := s;
end;
UnitMisc.AppendLog('MenuItem format=' + self.CTRLClickedItem.GetFormatName );
if (self.KeyPressedOverride(s, self.CTRLClickedItem)) then begin
EXIT;
end;
LastStringSelected := s;
if (self.DoMoveSelectedToTop) then
ClipQueue.MoveToStart( ClipQueue.IndexOf(self.CTRLClickedItem) );
//
// Legacy Note: The ClipItem may have no handle and no format and may
// only contain the plain text version of an item
//
pasted := false;
if (self.CTRLClickedItem <> nil) and (self.CTRLClickedItem.GetFormat <> 0) then begin
if (not Paste.GetKeyboardMimicOnce) then begin
if (self.CTRLClickedItem.GetFormat = Windows.CF_UNICODETEXT) or
(FrmConfig.cbPasteComplex.checked) then begin
UnitMisc.AppendLog('Sending UNICODE by default ');
self.SendText('', self.CTRLClickedItem);
pasted := true;
UnitMisc.AppendLog('inserting done');
end;
end;
end;
if (not pasted) then begin
UnitMisc.AppendLog('Sending plaing text ');
self.SendText(s);
UnitMisc.AppendLog('inserting done');
end;
self.HandleFormMode;
end;
procedure TFrmMainPopup.FlushTextItemsClickEvent(Sender: TObject);
begin
ClipQueue.ClearQueue;
self.FullMode := false;
self.ShowPopupWithFocusRules;
end;
procedure TFrmMainPopup.EditHistoryItemClickEvent(Sender : TObject);
begin
// show the edit window
// re-show the popup when the edit window it closed
Windows.SetForegroundWindow(frmClipboardManager.Handle);
frmClipboardManager.ShowModal;
self.ShowPopupWithFocusRules;
end;
procedure TFrmMainPopup.OtherItemClickEvent(Sender: TObject);
var i : integer;
ci : TClipItem;
begin
if (Sender is TMenuItem) then begin
with Sender as TMenuItem do begin
i := ImageIndex;
end;
ci := OtherQueue.GetClipItem(i);
end else begin
ci := TClipItem(Sender);
end;
// preview only
if (KeyboardQuery.IsPressed(VK_SHIFT)) then begin
FrmPreview.SetPicture;
ci.GetDIB(FrmPreview.imgPreview.picture);
self.ShowPreviewForm;
EXIT;
end;
// Copy - with no paste
if (KeyboardQuery.IsPressed(VK_F1)) then begin
// try to clear phantom keystroke from entering other program
keybd_event(VK_F1, VkKeyScan(char(VK_F1)), KEYEVENTF_KEYUP, 0);
Paste.SetClipboardOnlyOnce;
end;
if (KeyboardQuery.IsPressed(VK_CONTROL) and (self.UseCtrlClickMenu)) then begin
if (self.ThreadAttach(self.HotKeyForeWindow)) then begin
Windows.SetForegroundWindow(self.Handle);
self.ThreadDetach;
end;
// Show the format in the "Paste as" Menu option
pmItemOptions.Items[0].Enabled := false;
pmItemOptions.Items[0].Caption := '&0 [no "paste as" format]';
pmItemOptions.Items[9].Enabled := false;
pmItemOptions.Items[9].Caption := '&A [no complex format]';
self.CTRLClickedItem := ci;
if (self.CTRLClickedItem <> nil) then begin
pmItemOptions.Items[0].Enabled := true;
pmItemOptions.Items[0].Caption := '&0 Paste' + self.CTRLClickedItem.GetFormatName;
pmItemOptions.Items[9].Enabled := true;
pmItemOptions.Items[9].Caption := '&A Make Permanent as ' + self.CTRLClickedItem.GetFormatName;
end;
pmItemOptions.Items.RethinkHotkeys;
pmItemOptions.Items[1].Caption := '[no run format]';
pmItemOptions.Items[1].Caption := '&1 Run ...';
pmItemOptions.Popup(self.TargetX, self.TargetY );
// make sure focus is returned
if (self.ThreadAttach(self.HotKeyForeWindow)) then begin
SetForegroundWindow(self.HotKeyForeWindow);
self.ThreadDetach;
end;
end else begin
Paste.SendText('', ci);
end;
// try to clear phantom keystroke from entering other program
keybd_event(VK_F1, VkKeyScan(char(VK_F1)), KEYEVENTF_KEYUP, 0);
end;
procedure TFrmMainPopup.FlushOtherItemsClickEvent(Sender: TObject);
begin
OtherQueue.ClearQueue;
self.FullMode := false;
self.ShowPopupWithFocusRules;
end;
procedure TFrmMainPopup.CurrentMenuItemClickEvent(Sender: TObject);
begin
if (self.KeyPressedOverride('', self.CurrentClipboard)) then begin
EXIT;
end;
UnitMisc.AppendLog('Sending Current Item ');
self.SendText('', self.CurrentClipboard);
UnitMisc.AppendLog('inserting done');
end;
procedure TfrmMainPopup.LastMenuItemClickEvent(Sender: TObject);
begin
UnitMisc.AppendLog('Inserting last selected string');
if (self.KeyPressedOverride(LastStringSelected)) then begin
EXIT;
end;
self.SendText(LastStringSelected);
end;
procedure TfrmMainPopup.CancelMenuItemClickEvent(Sender: TObject);
begin
// since using the keyboard takes away focus from the target
// window, it must be returned
if (self.PopupUseKB) then begin
if (self.ThreadAttach(self.HotKeyForeWindow)) then begin
Windows.SetForegroundWindow(self.HotKeyForeWindow);
self.ThreadDetach;
end;
end;
self.UseFormMode := false;
end;
procedure TfrmMainPopup.PermanentMenuItemClickEvent(sender: TObject);
var s : string;
pid : integer;
begin
with sender as tmenuitem do begin
s := TMenuITem(sender).hint;
pid := TMenuItem(sender).tag;
end;
if (pid <> - 1) then begin
FrmPermanent.PermFolderPush;
FrmPermanent.SetPermanentPath(FrmPermanent.PermFoldersGetItem(pid));
end;
self.PermanentMenuItemClickEvent(s);
if (pid <> -1) then begin
FrmPermanent.PermFolderPop;
end;
end;
procedure TFrmMainPopup.PermanentMenuItemClickEvent(s: string);
begin
MenuItemText := s;
if (self.KeyPressedOverride(s)) then begin
EXIT;
end;
self.SendText( s );
self.HandleFormMode;
end;
procedure TFrmMainPopup.PermanentGroupItemClickEvent(sender: TObject);
var s : string;
begin
with sender as tmenuitem do begin
s := Hint;
end;
self.PermanentGroupItemClickEvent(s);
end;
procedure TFrmMainPopup.PermanentGroupItemClickEvent(s: string);
begin
// Explicitly assign the permanent group to the current EXE
frmPermanent.SetPermanentPath(s);
FrmPermanent.AssignPIG(self.TargetEXE);
self.ShowPopupWithFocusRules;
end;
procedure TfrmMainPopup.PasteAllMenuItemClickEvent(sender: TObject);
var i : longint;
s : string;
begin
s := '';
for i := 0 to (ClipQueue.GetQueueCount - 1) do begin
if (Cardinal(i) = (ClipQueue.GetQueueCount - 1)) then begin
s := s + ClipQueue.GetItemText(i);
end else begin
s := s + ClipQueue.GetItemText(i) + #13#10;
end;
end;
self.SendText(s);
end;
procedure TfrmMainPopup.PasteSelectedMenuItemClickEvent(sender: TOBject);
var s : string;
begin
s := FrmPasteSelected.GetSelectedItems;
// the above windows takes away focus from target
// here, so it needs it back before pasting
if (not self.PopupUseKB) then begin
self.ThreadAttach(self.HotKeyForeWindow);
Windows.SetForegroundWindow(self.HotKeyForeWindow);
self.ThreadDetach;
end;
if (s <> '') then begin
self.SendText(s);
end else begin
self.CancelMenuItemClickEvent(self);
end;
end;
procedure TFrmMainPopup.FormModeMenuItemClickEvent(Sender: TObject);
begin
self.UseFormMode := not self.UseFormMode;
self.ShowPopupWithFocusRules;
end;
procedure TFrmMainPopup.NextFieldModeMenuItemClickEvent(Sender: TObject);
var b : boolean;
begin
b := self.UseFormMode;
self.UseFormMode := true;
self.HandleFormMode;
self.UseFormMode := b;
end;
procedure TFrmMainPopup.HandleFormMode;
var w : word;
begin
if self.UseFormMode then begin
// focus back on target window and control
// press tab
// get current target window control again
// re-show the popup
if (self.PopupUseKB) then begin
if (self.ThreadAttach(self.HotKeyForeWindow)) then begin
Windows.SetForegroundWindow(self.HotKeyForeWindow);
Windows.SetFocus(self.HotKeyTarget);
end else begin
showmessage('ERROR: Unable to paste into target');
exit;
end;
end;
w := VkKeyScan(#9);
keybd_event(VK_TAB, w, 0, 0);
sleep(10);
keybd_event(VK_TAB, w, KEYEVENTF_KEYUP, 0);
sleep(100);
if (self.PopupUseKB) then begin
self.ThreadDetach;
end;
self.GetTargetControl(self.HotKeyForeWindow, self.HotKeyTarget,
TargetX, TargetY);
self.ShowPopupWithFocusRules;
end;
end;
//
// ShowOnNextWindow - This lets another window cause the popup
// to show up on the text field that just lost focus
//
procedure TFrmMainPopup.ShowOnNextWindow(ShowPopup : boolean = true);
var h : THandle;
begin
Windows.SetLastError(ERROR_SUCCESS);
if (self.PopupShowing) then EXIT;
self.PopupShowing := true;
// find the current foreground window
// find the "next" window (which means below the current, not above)
// skip any invisible windows
h := Windows.GetForegroundWindow;
if (h = 0) then begin
UnitMisc.AppendLog('Can''t get foreground window', true);
end;
h := Windows.GetNextWindow(h, GW_HWNDNEXT);
if (h = 0) then begin
UnitMisc.AppendLog('Can''t get next window', true);
end;
while (not Windows.IsWindowVisible(h)) and (h <> 0) do begin
h := Windows.GetNextWindow(h, GW_HWNDNEXT);
if (h = 0) then begin
UnitMisc.AppendLog('Can''t get next window in loop', true);
end;
end;
// move back the the "next" window and attempt
// to make the previously focused control get keyboard focus again
if (ShowPopup) then begin
if (self.ThreadAttach(h)) then begin
Windows.SetForegroundWindow(h);
self.ThreadDetach;
end;
end;
self.HotKeyForeWindow := h;
self.GatherTargetWindowData;
if (ShowPopup) then begin
self.ShowPopupWithFocusRules;
end;
self.PopupShowing := false;
end;
function TFrmMainPopup.GetNextWindowProgramName: string;
var h : THandle;
i : integer;
begin
Windows.SetLastError(ERROR_SUCCESS);
// find the current foreground window
// find the "next" window (which means below the current, not above)
// skip any invisible windows
h := Windows.GetForegroundWindow;
i := 0;
while (h=0) and (i<10) do begin
h := Windows.GetForegroundWindow;
inc(i);
sleep(20);
end;
if (h = 0) then begin
UnitMisc.AppendLog('Can''t get foreground window', true);
end;
h := Windows.GetNextWindow(h, GW_HWNDNEXT);
i := 0;
while (h=0) and (i<10) do begin
h := Windows.GetForegroundWindow;
inc(i);
sleep(20);
end;
if (h = 0) then begin
UnitMisc.AppendLog('Can''t get next window', true);
end;
while (not Windows.IsWindowVisible(h)) and (h <> 0) do begin
h := Windows.GetNextWindow(h, GW_HWNDNEXT);
if (h = 0) then begin
UnitMisc.AppendLog('Can''t get next window in loop', true);
end;
end;
if (h <> 0) then begin
result := ExtractFilename(WindowHandleToEXEName(h));
end else begin
result := '';
end;
end;
procedure TFrmMainPopup.ShowOnSystemTray;
var h : THandle;
CursorPos : TPoint;
begin
Windows.SetLastError(ERROR_SUCCESS);
if (self.PopupShowing) then EXIT;
self.PopupShowing := true;
// find the current foreground window
// find the "next" window (which means below the current, not above)
// skip any invisible windows
h := Windows.GetForegroundWindow;
h := Windows.GetNextWindow(h, GW_HWNDNEXT);
while not Windows.IsWindowVisible(h) do begin
h := Windows.GetNextWindow(h, GW_HWNDNEXT);
end;
self.HotKeyForeWindow := h;
self.HotKeyTarget := 0;
Windows.GetCursorPos(CursorPos);
self.TargetX := CursorPos.x;
self.TargetY := CursorPos.Y;
Windows.SetForegroundWindow(self.Handle);
self.ShowPopup(CursorPos.x, CursorPos.y);
self.PopupShowing := false;
end;
procedure TFrmMainPopup.FullModeMenuItemClickEvent(Sender : TObject);
begin
//
// toggle Full->Configured and Configured->Full
//
self.FullMode := self.FullMode xor true;
self.ShowPopupWithFocusRules;
end;
procedure TFrmMainPopup.SendText(s: string; ci : TClipItem = nil);
var prefix : string;
begin
Windows.SetLastError(ERROR_SUCCESS);
//
// Since the popup may have stolen focus from the target,
// it must be given keyboard focus again
//
if (self.PopupUseKB) then begin
if (self.ThreadAttach(self.HotKeyForeWindow)) then begin
Windows.SetForegroundWindow(self.HotKeyForeWindow);
if (self.HotKeyTarget <> 0) then begin
Windows.SetFocus(self.HotKeyTarget);
end;
end else begin
showmessage('ERROR: Unable to paste into target');
EXIT;
end;
end;
prefix :=uppercase(leftstr(s,6));
if (prefix = '[KEYS]') then begin
Paste.SendTextWithKeystrokes(s);
end else if (FrmPermanent.IsComplexItem(s)) then begin
ci := FrmPermanent.GetComplexItem(s);
Paste.SendText('', ci);
MyFree(ci);
end else begin
Paste.SendText(s, ci);
end;
if (self.PopupUseKB) then begin
self.ThreadDetach;
end;
end;
{
--============================
-- // Thead utility methods //
--============================
Description: Mimic being part of the targeted window. This method is used
to get the keyboard focused item of an outside process and to associate a
popup menu with an outside process.
Update: Changed to allow ArsClip to paste into its own windows, like
Permanent Items.
}
function TfrmMainPopup.ThreadAttach(TargetWindow: cardinal) : boolean;
begin
If (ThreadAttached) then begin
showmessage('Error: Thread already attached');
self.Close;
end;
ThreadTarget := Windows.GetWindowThreadProcessId(TargetWindow, nil);
ThreadOurs := Windows.GetCurrentThreadId();
if (ThreadTarget <> ThreadOurs) then begin
result := Windows.AttachThreadInput(ThreadTarget, ThreadOurs, true);
end else begin
result := true;
end;
ThreadAttached := true;
end;
procedure TfrmMainPopup.ThreadDetach();
begin
{
If (not ThreadAttached) then begin
showmessage('Error: Thread not attached');
self.Close;
end;
}
if (ThreadTarget <> ThreadOurs) then begin
Windows.AttachThreadInput(ThreadTarget, ThreadOurs, false);
end;
ThreadAttached := false;
end;
{
--===========
-- // Etc. //
--===========
}
procedure TfrmMainPopup.AppendLog(s : string);
begin
if length(memo1.text) > 30000 then memo1.Text := '';
// Cheezy Debugging Info[tm]
// make sure we don't overflow the text, only accept 1000 characters
// at a time
memo1.Text := leftstr(s, 1000) + #13 + #10 + memo1.text;
end;
procedure TfrmMainPopup.btnHideClick(Sender: TObject);
begin
self.Hide;
end;
{
--====================
-- CTRL option menu items
--===================
}
procedure TFrmMainPopup.Run1Click(Sender: TObject);
var s : string;
i : integer;
begin
Windows.SetLastError(ERROR_SUCCESS);
//
// try to run it as a mail address if it fails
// the first time - report any error otherwise
// trim any whitespace - CRLFs
s := trim(self.MenuItemText);
if s = '' then EXIT;
while s[length(s)] in [#13, #10] do begin
s := Copy(s, 1, length(s) - 1);
end;
i := ShellAPI.ShellExecute(self.Handle,nil,
PChar(s),nil,nil,SW_NORMAL);
if (i <= 32) then begin
if (pos('@',s) <> 0) then begin
s := 'mailto:' + s;
i := shellAPI.ShellExecute(self.Handle,nil,
PChar(s),nil,nil,SW_NORMAL);
end;
end;
if (i <= 32) then begin
Windows.SetForegroundWindow(self.Handle);
ShowMessage(SysErrorMessage(i));
end;
//frmClipboardManager.SetIgnoreClipboard(false); // just incase
end;
procedure TFrmMainPopup.MakePermanentItem1Click(Sender: TObject);
begin
Windows.SetForegroundWindow(FrmPermanent.Handle);
frmPermanent.ShowWithNewItem(self.MenuItemText);
end;
procedure TFrmMainPopup.AMakePermanentas1Click(Sender: TObject);
begin
Windows.SetForegroundWindow(FrmPermanent.Handle);
frmPermanent.ShowWithNewComplexItem(self.CTRLClickedItem);
end;
procedure TFrmMainPopup.PasteusingMimicTyping1Click(Sender: TObject);
begin
Paste.SetKeyboardMimicOnce;
self.SendText(self.MenuItemText);
end;
procedure TFrmMainPopup.Placeonclipboard1Click(Sender: TObject);
var i : integer;
ci : TClipItem;
begin
//
// always default to the Unicode version, if available
//
Paste.SetClipboardOnlyOnce;
i := ClipQueue.IndexOf(self.MenuItemText);
ci := ClipQueue.GetClipItem(i);
if (ci <> nil) then begin
if (ci.GetFormat = CF_UNICODETEXT) then begin
self.SendText('',ci);
EXIT;
end;
end;
self.SendText(self.MenuItemText);
end;
procedure TFrmMainPopup.Preview1Click(Sender: TObject);
begin
FrmPreview.SetText(self.MenuItemText);
self.ShowPreviewForm;
end;
procedure TFrmMainPopup.back1Click(Sender: TObject);
begin
self.ShowPopupWithFocusRules;
end;
procedure TFrmMainPopup.PasteusingSHIFTINS1Click(Sender: TObject);
begin
Paste.SetUsePasteSIOnce;
self.SendText(self.MenuItemText);
end;
procedure TFrmMainPopup.PasteusingCTRLV1Click(Sender: TObject);
begin
Paste.SetUsePasteCVOnce;
self.SendText(self.MenuItemText);
end;
procedure TFrmMainPopup.N0PasteasRichText1Click(Sender: TObject);
begin
// Paste as Plain text when Complex is default
// Paste as Rich Text when not using Complex by default
if (FrmConfig.cbPasteComplex.Checked) then begin
Paste.SendText(self.MenuItemText, nil);
end else begin
Paste.SendText(self.MenuItemText, self.CTRLClickedItem);
end;
end;
function TFrmMainPopup.GetLastStringSelected: string;
begin
result := self.LastStringSelected;
end;
function TFrmMainPopup.GetUseFormMode: boolean;
begin
result := self.UseFormMode;
end;
function TFrmMainPopup.GetFullMode: boolean;
begin
result := self.FullMode;
end;
function TFrmMainPopup.GetDoMoveSelectedToTop: boolean;
begin
result := DoMoveSelectedToTop;
end;
function TFrmMainPopup.GetDoRememberHistory: boolean;
begin
result := DoRememberHistory;
end;
function TFrmMainPopup.GetDoShowCurrentItem: boolean;
begin
result := DoShowCurrentItem;
end;
function TFrmMainPopup.GetDoShowEditHistory: boolean;
begin
result := DoShowEditHistory;
end;
function TFrmMainPopup.GetDoShowFormMode: boolean;
begin
result := DoShowFormMode;
end;
function TFrmMainPopup.GetDoShowLast: boolean;
begin
result := DoShowLast;
end;
function TFrmMainPopup.GetDoShowPasteAll: boolean;
begin
result := DoShowPasteAll;
end;
function TFrmMainPopup.GetDoShowPermanentItemGroups: boolean;
begin
result := DoShowPermanentItemGroups;
end;
function TFrmMainPopup.GetDoShowPermanentItemSubmenu: boolean;
begin
result := DoShowPermanentItemSubmenu
end;
function TFrmMainPopup.GetUsePermanentItems: boolean;
begin
result := UsePermanentItems;
end;
procedure TFrmMainPopup.MimicTyping1Click(Sender: TObject);
begin
Paste.AssignPaste(self.TargetEXE, PASTE_MIMIC);
end;
procedure TFrmMainPopup.N2SHIFTINSERT1Click(Sender: TObject);
begin
Paste.AssignPaste(self.TargetEXE, PASTE_SHIFT_INS);
end;
procedure TFrmMainPopup.N3CTRLV1Click(Sender: TObject);
begin
Paste.AssignPaste(self.TargetEXE, PASTE_CTRL_V);
end;
procedure TFrmMainPopup.N4ClipboardOnly1Click(Sender: TObject);
begin
Paste.AssignPaste(self.TargetEXE, PASTE_CLIPBOARD);
end;
procedure TFrmMainPopup.N5Default1Click(Sender: TObject);
begin
Paste.AssignPaste(self.TargetEXE, PASTE_DEFAULT);
end;
end.