You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
RnQ/RnQ/mainDlg.pas

1655 lines
48 KiB
Plaintext

{
This file is part of R&Q.
Under same license
}
unit mainDlg;
{$I RnQConfig.inc}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, StdCtrls, ExtCtrls, Menus,
Generics.Collections, ActiveX, Threading,
RDGlobal, RQMenuItem, RnQDialogs, RnQTrayLib, ICQContacts, chatDlg,
pluginLib, utilLib, groupsLib, roasterLib, GR32, CLBox, System.Actions;
{$I NoRTTI.inc}
type
TRnQmain = class(TForm)
timer: TTimer;
procedure FormShow(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormResize(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure displayHint(Sender: TObject);
procedure AppActivate(Sender: TObject);
procedure FormHide(Sender: TObject);
procedure OnTimer(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure CLKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure WMDisplayChange(var pMsg: TWMDisplayChange); message WM_DISPLAYCHANGE;
procedure WMExitSizeMove(var pMsg: TMessage); message WM_EXITSIZEMOVE;
procedure OnTrayEvent(Sender: TObject; ev: TTrayEvent);
private
FMouseInControl: Boolean;
FToggling: Boolean;
procedure CMMouseEnter(var Msg: TMessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var Msg: TMessage); message CM_MOUSELEAVE;
procedure WMNCActivate(var Msg: TWMNCActivate); message WM_NCACTIVATE;
procedure WMRestoreApp(var Msg: TMessage);
public
oldHandle: THandle;
CLBox: TCLBox;
procedure InitDocument;
procedure UpdateContactCount;
procedure ReStart(Sender: TObject);
procedure WndProc(var Msg: TMessage); override;
procedure UpdateCaption;
function clickedGroupList: TRnQCList;
procedure AddContactsAction(Sender: TObject);
procedure SendContactsAction(Sender: TObject);
procedure ToggleVisible;
procedure ToggleFilter;
procedure DoAutosize;
procedure CloseAllChildWindows;
procedure UpdateStatusGlyphs;
// procedure CreateParams(var Params: TCreateParams); override;
// procedure wmNCHitTest(VAR Msg: TWMNCHitTest); message WM_NCHITTEST;
procedure onCloseSomeWindows(Sender: TObject; var Action: TCloseAction);
procedure previewFormKeyPress(Sender: TObject; var Key: Char);
procedure MemoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
// function AddMainMenuItem(wPar: WPARAM; lPar: LPARAM): Integer; cdecl;
function AddContactMenuItem(pMI: PCLISTMENUITEM): Integer; // cdecl;
{ function AddContactMenuItem(pPluginProc : Pointer; menuIcon: hIcon; menuCaption:String;
menuHint:string; //procIdx : Integer;
position : Integer;
PopupName : String; popupPosition : Integer;
hotKey : DWORD; PicName : String = ''):integer; }
// function UpdateContactMenuItem(menuHandle: hmenu; pMI : PCLISTMENUITEM): Integer;// cdecl;
procedure UpdateContactMenuItem(menuHandle: hmenu; pMI: PCLISTMENUITEM); // cdecl;
procedure DelContactMenuItem(menuHandle: hmenu);
procedure OnPluginMenuClick(Sender: TObject);
procedure CreateParams(var Params: TCreateParams); override;
procedure SaveFormPositionForCurrentMonitorCount;
procedure DefaultHandler(var Message); override;
procedure StopTimer(ID: Integer);
procedure StartTimer(ID, Time: Integer);
end; // TmainFrm
TFormPos = class
Left: Integer;
Top: Integer;
end;
var
RnQmain: TRnQmain;
LastMonCnt: Integer;
MonPositions: TDictionary;
WM_FINDINSTANCE: Integer;
implementation
uses
UxTheme, Themes,
aboutDlg, selectContactsDlg,
incapsulate, // dbDlg,
outboxDlg, Types, globalLib,
events, themesLib, history, iniLib,
// smsDlg,
Clipbrd, ShellAPI, strutils, langLib, outboxLib,
RnQGlobal, RnQPics,
hook,
RDFileUtil, RDUtils, RnQSysUtils,
RQUtil, RQLog, RnQdbDlg, RnQTips, tipDlg,
Protocols_All,
ICQCommon, ICQConsts, ICQSession,
Protocol_ICQ, Nodes,
RnQLangs, RnQMacros, RnQStrings, RnQNet, RnQGraphics32, RnQ_Avatars,
menusUnit, statusform, Math;
{$R *.DFM}
procedure TRnQmain.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.ExStyle := (Params.ExStyle and not WS_SYSMENU and (not WS_EX_WINDOWEDGE) and (not WS_EX_STATICEDGE) and (not WS_EX_DLGMODALFRAME) and (not WS_EX_CLIENTEDGE));
Params.Style := (Params.Style and (not WS_CAPTION) and (not DS_MODALFRAME) and (not WS_DLGFRAME) and (not WS_THICKFRAME));
Params.Style := (Params.Style or WS_SYSMENU or WS_MAXIMIZEBOX or WS_MINIMIZEBOX and not WS_SIZEBOX);
end;
procedure TRnQmain.FormShow(Sender: TObject);
begin
utilLib.dockSet;
autosizeDelayed := True;
MainFormHandleUpdate;
applySnap;
{$IFDEF DEBUG_PACKETS}
// Account.AccProto.getMyInfo.ViewInfo;
Showlogwindow1Click(Sender);
{$ENDIF DEBUG_PACKETS}
CLBox.UpdateMenus;
end;
procedure TRnQmain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
CanClose := not QuitConfirmation or (MessageDlg(GetTranslation('Really quit?'), mtConfirmation, [mbYes, mbNo]) = mrYes);
end;
procedure TRnQmain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
quit;
end;
procedure TRnQmain.CloseAllChildWindows;
var
i: Integer;
c: Tcomponent;
begin
i := childWindows.Count - 1;
while i >= 0 do
begin
c := childWindows.Items[i];
if c is TForm then
with c as TForm do
if visible then
begin
// childWindows.Items[i] := NIL;
close;
end;
dec(i);
end;
i := componentcount - 1;
while i >= 0 do
begin
c := components[i];
if c is TForm then
with c as TForm do
if visible then
close;
dec(i);
end;
FreeAndNil(RnQdbFrm);
end; // closeAllChildWindows
procedure TRnQmain.UpdateCaption;
var
MyInf: TICQContact;
begin
MyInf := NIL;
if Assigned(Account.AccProto) then
MyInf := Account.AccProto.getMyInfo;
if Assigned(MyInf) then
// and Assigned(Account.AccProto.MyInfo) then
with MyInf do
caption := template(rosterTitle, ['%nick%', nick, '%uin%', uin2Show, '%build%', IntToStr(RnQBuild)])
else
caption := template(rosterTitle, ['%title%', Application.Title, '%nick%', Str_unk, '%uin%', Str_unk, '%build%',
IntToStr(RnQBuild)]);
chatFrm.caption := RnQmain.caption + ' - ' + getTranslation('Chat window');
end; // updateCaption
procedure TRnQmain.ToggleVisible;
var
timeout: Integer;
begin
if FToggling then
Exit;
try
FToggling := True;
if formVisible(Self) and (windowstate <> wsMinimized) then
begin
if minimizeRoster then
begin
{ tipfrm is hided anyway, but if we don't do it manually it will reapper
{ just as the roster repops up }
TipsHideAll;
// ShowWindow()
// if transparency.forRoster then
// AnimateWindow(self.Handle, 1000, AW_HIDE);
// else
// AnimateWindow(self.Handle, 100, AW_BLEND or AW_HIDE);
if Self.Floating then
windowstate := wsMinimized
else if docking.Dock2Chat and docking.Docked2chat then
chatFrm.windowstate := wsMinimized;
end;
{ sometimes form is not hided after minimization, maybe it is a matter of
{ timeouts. this loop could fix the problem }
timeout := 0;
if docking.Dock2Chat and docking.Docked2chat and not Self.Floating then
repeat
if timeout > 0 then
sleep(10);
chatFrm.Hide;
inc(timeout);
until not formVisible(chatFrm) or (timeout = 100)
else
repeat
if timeout > 0 then
sleep(10);
Hide;
inc(timeout);
until not formVisible(Self) or (timeout = 100);
end
else
begin
{ if Self.Floating then
if windowstate=wsMinimized then
windowstate:=wsNormal
else
windowstate:=wsMinimized;
}
// if windowstate = wsNormal then
if docking.Dock2Chat and docking.Docked2chat and not Self.Floating then
begin
try
chatFrm.show;
except
end;
Application.BringToFront;
ForceForegroundWindow(chatFrm.Handle);
end
else
begin
try
// if transparency.forRoster then
// AnimateWindow(self.Handle, 50, AW_ACTIVATE);
// else
// AnimateWindow(self.Handle, 100, AW_BLEND);
if windowstate <> wsMinimized then
windowstate := wsMinimized;
windowstate := wsNormal;
show;
except
end;
Application.BringToFront;
ForceForegroundWindow(Handle);
end;
end;
finally
FToggling := False;
MainFormHandleUpdate;
end;
end; // ToggleVisible
procedure TRnQmain.ToggleFilter;
begin
if FilterPos < 2 then
FilterPos := 2
else if filterBarOnTop then
FilterPos := 0
else
FilterPos := 1;
CLBox.InitSettings;
CLBox.FocusFilter;
end;
procedure TRnQmain.AddContactsAction(Sender: TObject);
var
wnd: TselectCntsFrm;
cl: TRnQCList;
begin
wnd := (Sender as TControl).Parent as TSelectCntsFrm;
cl := wnd.SelectedList;
cl.resetEnumeration;
while cl.hasMore do
AddToRoster(cl.getNext);
cl.free;
wnd.close;
end; // AddContactsAction
procedure TRnQmain.FormResize(Sender: TObject);
begin
autosizeDelayed := True;
end;
procedure TRnQmain.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
function its(sc: Tshortcut): Boolean;
var
k: Word;
s: TShiftState;
begin
ShortCutToKey(sc, k, s);
Result := (k = Key) and (s = Shift);
end; // its
var
i: Integer;
begin
if (Key = VK_ESCAPE) and not CLBox.IsFilterFocused and not CLBox.IsMenuFocused then
ToggleVisible
else if (Shift = [ssAlt]) and (Key = VK_F4) then
Close
else if (Shift = [ssCtrl]) and (Key = VK_F) then
begin
ToggleFilter;
Key := 0;
end else
for i := 0 to length(macros) - 1 do
if not macros[i].sw and its(macros[i].hk) then
executeMacro(macros[i].opcode);
end;
procedure TRnQmain.SendContactsAction(Sender: TObject);
var
// i:integer;
// s : String;
s: RawByteString;
cnt: TICQContact;
wnd: TselectCntsFrm;
cl: TRnQCList;
begin
wnd := (Sender as Tcontrol).parent as TselectCntsFrm;
cl := wnd.selectedList;
if not cl.empty then
begin
s := (wnd.extra as Tincapsulate).str;
if s > '' then
begin
// cnt := contactsDB.get(TICQContact, s);
cnt := wnd.proto.getContact(s);
begin
Account.outbox.add(OE_CONTACTS, cnt, 0, cl);
if Assigned(outboxFrm) then
outboxFrm.updateList;
end;
end;
end;
cl.free;
wnd.extra.free;
wnd.close;
end;
// change or add user
procedure TRnQmain.DoAutosize;
var
Y, limit, delta: Integer;
begin
if not autoSizeRoster or docking.active or (not Self.Floating) or not formVisible(Self) then
Exit;
if autosizeFullRoster then
Y := CLBox.GetFullMaxY
else
Y := CLBox.GetOnlineMaxY;
if Y > 20 then
begin
inc(Y, 5);
// if bar.Visible then inc(y, sbar.height);
// limit:=desktopWorkArea.Bottom - self.clientToScreen(point(0, 0)).y;
if autosizeUp then
begin
limit := Top + Height - Screen.MonitorFromWindow(Self.Handle).WorkareaRect.Top;
// limit:= Screen.DesktopTop + Screen.DesktopHeight - clientToScreen(point(0,0)).y;
if Y > limit then
Y := limit;
delta := Y - clientheight;
Top := Top - delta;
clientheight := Y;
end
else
begin
limit := Screen.MonitorFromWindow(Self.Handle).WorkareaRect.Bottom - Self.clientToScreen(Types.Point(0, 0)).Y;
// limit:= Screen.DesktopTop + Screen.DesktopHeight - clientToScreen(point(0,0)).y;
if Y > limit then
Y := limit;
clientheight := Y;
end;
SaveFormPositionForCurrentMonitorCount;
end;
end; // DoAutosize
procedure TRnQmain.AppActivate(Sender: TObject);
begin
inactiveTime := 0;
TipsShowTop;
end;
function TRnQmain.clickedGroupList: TRnQCList;
var
c: TICQContact;
begin
Result := TRnQCList.Create;
for c in Account.AccProto.readList(LT_ROSTER) do
if Assigned(clickedNode) and (c.group = clickedNode.groupId) then
Result.add(c);
end; // clickedGroupList
// group to normal
procedure TRnQmain.displayHint(Sender: TObject);
begin
if Assigned(chatFrm) and chatFrm.Visible then
chatFrm.setStatusbar(Application.Hint);
// HM_url: chatFrm.setStatusbar(getURLfromFav(application.Hint));
end;
{ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * }
function GetActiveMonitorCount: Integer;
var
lpDisplayDevice: TDisplayDevice;
dwFlags: DWORD;
cc: DWORD;
begin
lpDisplayDevice.cb := sizeOf(lpDisplayDevice);
dwFlags := 0;
cc := 0;
Result := 0;
while EnumDisplayDevices(nil, cc, lpDisplayDevice, dwFlags) do
begin
inc(cc);
if lpDisplayDevice.StateFlags and $01 {AttachedToDesktop} <> 0 then
inc(Result)
end;
end;
procedure TRnQmain.SaveFormPositionForCurrentMonitorCount;
var
size: TFormPos;
begin
size := TFormPos.Create;
size.Top := Top;
size.Left := Left;
MonPositions.AddOrSetValue(LastMonCnt, size);
size.Free;
end;
procedure TRnQmain.WMDisplayChange(var pMsg: TWMDisplayChange);
var
size: TFormPos;
cnt: Integer;
begin
cnt := GetActiveMonitorCount;
if LastMonCnt <> cnt then
begin
LastMonCnt := cnt;
if MonPositions.TryGetValue(LastMonCnt, size) then
begin
TTask.Create(procedure
begin
sleep(1000);
TThread.Synchronize(nil, procedure
begin
Left := size.Left;
Top := size.Top;
end);
end, TThreadPool.Default).Start;
end;
end;
end;
procedure TRnQmain.WMExitSizeMove(var pMsg: TMessage);
begin
SaveFormPositionForCurrentMonitorCount;
end;
procedure TRnQmain.UpdateStatusGlyphs;
begin
if Assigned(Account.AccProto) then
begin
if Account.AccProto.IsOnline then
CLBox.UpdateStatusImage(Account.AccProto.getStatuses[Account.AccProto.getStatus].ImageName)
else
CLBox.UpdateStatusImage(status2imgName(byte(SC_OFFLINE), False));
end
else
begin
CLBox.UpdateStatusImage(status2imgName(byte(SC_UNK), False));
end;
{ statusBtn.ImageName := statusImgName;
//theme.getPic(statusImgName, statusBtn.glyph);
statusBtn.Repaint;
visibilityBtn.ImageName := visibilityImgName;
//theme.getPic(visibilityImgName, visibilityBtn.glyph);
visibilityBtn.Repaint; }
end;
procedure TRnQmain.FormHide(Sender: TObject);
begin
clickedContact := nil;
// dockSet(FALSE);
docking.appbarFlag := False;
// utilLib.dockSet;
dockSet(Self.Handle, False, WM_DOCK);
CLBox.UpdateMenus;
end;
procedure TRnQmain.WndProc(var Msg: TMessage);
var
i: Integer;
ScrLeft, ScrWidth: Integer;
R: TRect;
begin
case Msg.Msg of
{ WM_COMMAND:
try
case TWMCommand(msg).ItemID of
// WA_FILE_PLAY : Label1.Caption := 'Play file';
WINAMP_BUTTON1 : executeMacro(OP_PLR_PREV); // 'Button prev track';
WINAMP_BUTTON3 : executeMacro(OP_PLR_PAUSE); //'Play/Stop';
WINAMP_BUTTON4 : executeMacro(OP_PLR_STOP); //'Pause';
WINAMP_BUTTON5 : executeMacro(OP_PLR_NEXT); //'Button next track';
// WINAMP_REW5S : Label1.Caption := 'rewind 5 sec';
// WINAMP_FFWD5S : Label1.Caption := 'forward 5 sec'
else ...
inherited;
end;
except //showmessage ('WM_COMMAND error!')
end;
}
WM_QUIT:
begin
inherited;
quit;
end;
WM_SHOWWINDOW:
if ((Msg.WParam = 0) or running) and Floating then
inherited;
WM_HOTKEY:
if not locked and hotkeysEnabled then
executeMacro(macros[Msg.WParam].opcode);
WM_SYSCOMMAND:
case Msg.WParam and $FFF0 of // first four bits are reserved
SC_CLOSE:
toggleVisible;
SC_MINIMIZE:
toggleVisible;
else
autosizeDelayed := TRUE;
inherited;
end;
WM_MOVING:
begin
if not docking.Enabled then
begin
inherited;
docking.Active := False;
Exit;
end;
i := MousePos.X;
// ScrWidth := screen.width
// r := Screen.MonitorFromWindow(self.Handle).WorkareaRect;
R := desktopWorkArea(mainDlg.RnQmain.Handle);
begin
ScrWidth := R.Right;
ScrLeft := R.Left;
end;
// limit:=Screen.MonitorFromWindow(self.Handle).WorkareaRect.Bottom - self.clientToScreen(point(0, 0)).y;
// if not docking.active and ((iscreen.width-DOCK_SNAP)) then
if not docking.active and ((i < ScrLeft + DOCK_SNAP) or (i > ScrWidth - DOCK_SNAP)) then
begin
docking.active := TRUE;
docking.pos := DP_right;
if i < ScrLeft + DOCK_SNAP then
docking.pos := DP_left;
docking.bakOfs := Types.Point(MousePos.X - boundsrect.Left, MousePos.Y - boundsrect.Top);
docking.bakSize := Types.Point(Width, Height);
end;
if docking.active and (i > ScrLeft + DOCK_SNAP) and (i < ScrWidth - DOCK_SNAP) then
begin
docking.active := False;
with TRect(Pointer(Msg.LParam)^) do
begin
Left := MousePos.X - docking.bakOfs.X;
Top := MousePos.Y - docking.bakOfs.Y;
Right := Left + docking.bakSize.X;
Bottom := Top + docking.bakSize.Y;
end;
end;
utilLib.dockSet(TRect(Pointer(Msg.LParam)^));
if not docking.active then
inherited;
end;
WM_SIZING:
begin
if docking.active then
utilLib.dockSet(TRect(Pointer(Msg.LParam)^));
inherited;
end;
//WM_MOUSEHOVER:
// CMMouseEnter(msg);
//WM_MOUSELEAVE:
// MMouseLeave(msg);
WM_ENTERMENULOOP:
begin
inherited;
end;
WM_EXITMENULOOP:
begin
inherited;
end;
WM_WTSSESSION_CHANGE:
// begin
case Msg.WParam of
WTS_CONSOLE_CONNECT:
isLocked := False;
// msgdlg('WTS_CONSOLE_CONNECT', mtInformation);
WTS_CONSOLE_DISCONNECT:
isLocked := TRUE;
// msgdlg('WTS_CONSOLE_DISCONNECT', mtInformation);
WTS_REMOTE_CONNECT:
isLocked := False;
// msgdlg('WTS_REMOTE_CONNECT', mtInformation);
WTS_REMOTE_DISCONNECT:
isLocked := TRUE;
// msgdlg('WTS_REMOTE_DISCONNECT', mtInformation);
WTS_SESSION_LOGON:
isLocked := False;
// msgdlg('WTS_SESSION_LOGON', mtInformation);
WTS_SESSION_LOGOFF:
isLocked := TRUE;
// msgdlg('WTS_SESSION_LOGOFF', mtInformation);
WTS_SESSION_LOCK:
isLocked := TRUE;
// msgdlg('WTS_SESSION_LOCK', mtInformation);
WTS_SESSION_UNLOCK:
isLocked := False;
// msgdlg('WTS_SESSION_UNLOCK', mtInformation);
{ WTS_SESSION_REMOTE_CONTROL:
begin
msgdlg('WTS_SESSION_REMOTE_CONTROL', mtInformation);
// GetSystemMetrics(SM_REMOTECONTROL);
end; }
// else
// msgdlg('WTS_Unknown', mtInformation);
end;
else
inherited;
end;
end; // wndproc
procedure TRnQmain.OnTimer(Sender: TObject);
procedure updateClocks;
var
i: Integer;
begin
if Assigned(childWindows) then
with childWindows do
begin
i := Count - 1;
while i >= 0 do
begin
if TObject(Items[i]) is TRnQViewInfoForm then
TRnQViewInfoForm(Items[i]).UpdateClock;
dec(i);
end;
end;
end; // updateClocks
procedure processOutbox;
var
oe: Toevent;
begin
if outboxCount > 0 then
dec(outboxCount);
if outboxCount = 0 then
if Assigned(Account.AccProto) and Account.AccProto.IsOnline and outboxprocessChk then
begin
oe := Account.outbox.popVisible;
if oe = NIL then
Exit;
outboxCount := timeBetweenMsgs;
if Assigned(outboxFrm) then
outboxFrm.updateList;
processOevent(oe);
oe.free;
end;
end; // processOutbox
var
i: Integer;
vi1: TRnQViewInfoForm;
Fcs: THandle;
cnt: TICQContact;
cntarr: TArray;
aNewDawn: Boolean; // TRUE once after each midnight
// vLastInput : DWord;
IsSSRuning: BOOL;
b: Boolean;
begin
aNewDawn := False;
if not running then
Exit;
// things to do once per second
{ flapSecs:=succ(flapSecs) mod 10;
if flapSecs = 0 then
begin
if SendedFlaps >= ICQMaxFlaps then
icq.sock.Resume;
SendedFlaps := 0;
end; }
if not Assigned(Account.AccProto) then
Exit;
// hide taskbar button
hideTaskButtonIfUhave2;
// trackingMouse;
longdelayCount := succ(longdelayCount) mod 50;
reconnectdelayCount := succ(reconnectdelayCount) mod boundInt(toReconnectTime, 50, 600);
if longdelayCount = 1 then
begin
aNewDawn := trunc(now) - trunc(lastOnTimer) = 1;
lastOnTimer := now;
// windows colors could have been changed, so lets recalculate "selectedColor"
selectedColor := blend(clHighlight, clBtnFace, 0.4);
// trayicon could disappear on crash, lets replace it
if Assigned(StatusIcon) and Assigned(StatusIcon.TrayIcon) then
StatusIcon.TrayIcon.Update;
// update recently offline
if EnableRecentlyOffline then
begin
cntarr := CLBox.GetContacts(d_recent);
if Length(cntarr) > 0 then
for cnt in cntarr do
if Assigned(cnt) then
if not TICQContact(cnt).IsRecent then
roasterLib.Update(TICQContact(cnt));
SetLength(cntarr, 0);
end;
// each 24hours check for updates
if CheckUpdate.Enabled and (Now - CheckUpdate.Last > CheckUpdate.Every) and not CheckUpdate.Checking and not StartingLock then
begin
CheckUpdate.AutoChecking := True;
Check4Update;
end;
end;
/// ////////////////// USER RELATED EVENTS //////////////////////
if usertime < 0 then
Exit;
inc(usertime); // keep track of user time
if aNewDawn then // if new day begin
begin
if Account.AccProto is TicqSession then
TicqSession(Account.AccProto).applyBalloon;
CheckBDays;
end;
// have messages been seen
if AutoConsumeEvents and Assigned(chatFrm) and chatFrm.IsVisible then
chatFrm.SawAllHere;
processOutbox;
// query contacts infos
if usertime mod 20 = 0 then
begin
if Assigned(retrieveQ) and (Account.AccProto.IsOnline) and not retrieveQ.empty then
begin
Account.AccProto.GetProfile(retrieveQ.getAt(0).UID2cmp);
retrieveQ.delete(0);
SaveListsDelayed := True;
end;
if Assigned(reqAvatarsQ) and Account.AccProto.AvatarsSupport and not reqAvatarsQ.empty then
begin
DownloadAvatar(TICQCOntact(reqAvatarsQ.getAt(0)));
reqAvatarsQ.delete(0);
end;
// if Assigned(reqXStatusQ) and not reqXStatusQ.empty and Assigned(Account.AccProto) and Account.AccProto.IsOnline then
// begin
// TicqSession(Account.AccProto.ProtoElem).RequestXStatus(reqXStatusQ.getAt(0).uid);
// reqXStatusQ.delete(0);
// end;
end;
if Self.Floating then
begin
Fcs := getFocus;
// Fcs := GetForegroundWindow;
if (Self.Floating and not childParent(Fcs, Self.Handle)) or (not Self.Floating and not childParent(Fcs, chatFrm.Handle)) then
inc(inactiveTime)
else
inactiveTime := 0;
end;
{ autohide triggers if
{ - it is enabled
{ - time set has passed
{ - the windows is visible
{ - the mouse is not over the window
}
if inactivehide and (inactiveTime >= inactivehideTime) and formVisible(Self) and not into(MousePos, Self.boundsrect)
// and not formVisible(xStatusForm)
// and not formVisible(xMRAStatusForm)
then
toggleVisible;
TipsProced;
// decay events
i := 0;
with eventQ do
while i < Count do
try
with Thevent(Items[i]) do
if expires = 0 then
begin
free;
removeAt(i);
end
else
begin
if expires > 0 then
dec(expires);
inc(i);
end;
except
end;
// do blink!
blinkCount := succ(blinkCount) mod blinkSpeed;
if blinkCount = 0 then
begin
blinking := not blinking;
if Assigned(StatusIcon) then
begin
if StatusIcon.TrayIcon.Hidden and not BossMode.isBossKeyOn then
StatusIcon.TrayIcon.Show
else if not StatusIcon.TrayIcon.Hidden and BossMode.isBossKeyOn then
StatusIcon.TrayIcon.Hide;
StatusIcon.Update;
end;
end;
if saveDBtimer2 > 0 then
begin
dec(saveDBtimer2);
if saveDBtimer2 = 0 then
// saveDB;
begin
saveListsDelayed := False;
// saveCfgDelayed := false;
saveInboxDelayed := False;
saveOutboxDelayed := False;
saveGroupsDelayed := False;
saveAllListsAsync(Account.ProtoPath, Account.AccProto, AllProxies);
end;
if saveDBtimer2 > 3000 then
saveDBtimer2 := 3000;
end;
if showRosterTimer > 0 then
begin
dec(showRosterTimer);
if showRosterTimer = 0 then
if not formVisible(Self) then
toggleVisible();
end;
if (reconnectdelayCount = 0) and running then
begin
// auto-reconnection
if StayConnected and Account.AccProto.IsOffline and ConnectionAvailable then
begin
Account.AccProto.SetStatus(LastStatus, True);
Inc(toReconnectTime, 50);
BoundInt(toReconnectTime, 50, 600);
end;
if ConnectOnConnection and Account.AccProto.IsOffline and not enteringProtoPWD and (LastStatusUserSet <> Byte(SC_OFFLINE)) and ConnectionAvailable then
Account.AccProto.SetStatus(LastStatusUserSet, True);
end;
if longdelayCount = 0 then
begin
// screen size could change, so update window position
if docking.active then
utilLib.dockSet
else
begin
fixWindowPos(Self);
fixWindowPos(chatFrm);
end;
// runs along the whole roster
b := False;
// i := 0;
// with Account.AccProto, readList(LT_ROSTER) do
// while i < Count do
// begin
// with getAt(i) do
// with TCE(data^) do
// if toQuery then
// if CntIsLocal then
// begin
// b := TRUE;
// toQuery := False;
// incDBTimer;
// retrieveQ.add(getAt(i));
// end;
// inc(i);
// end;
saveDBtimer2 := min(saveDBtimer2, 600);
if not fantomWork then
begin
if b then
saveListsDelayed := TRUE;
if saveCfgDelayed then
begin
UpdateProperties;
saveListsDelayed := False;
saveCfgDelayed := False;
saveInboxDelayed := False;
saveOutboxDelayed := False;
saveGroupsDelayed := False;
saveDBtimer2 := 0;
saveAllListsAsync(Account.ProtoPath, Account.AccProto, AllProxies);
end;
if saveInboxDelayed or saveOutboxDelayed or saveListsDelayed or saveGroupsDelayed or saveCfgDelayed then
begin
saveListsDelayed := False;
saveCfgDelayed := False;
saveInboxDelayed := False;
saveOutboxDelayed := False;
saveGroupsDelayed := False;
saveDBtimer2 := 0;
saveAllListsAsync(Account.ProtoPath, Account.AccProto, AllProxies);
end;
end;
end;
if autosizeDelayed then
autosizeDelayed := False;
// things to do twice per second
delayCount := succ(delayCount) mod 5;
if delayCount = 0 then
begin
FlushLogPktFile();
FlushLogEvFile();
updateClocks();
with updateViewInfoQ do
begin
resetEnumeration;
while hasMore do
begin
// if MainProto.ProtoElem is TicqSession then
begin
vi1 := findViewInfo(getNext);
if Assigned(vi1) then
begin
vi1.updateInfo;
if not formVisible(vi1) then
begin
showForm(vi1);
{ if vi1.readOnlyContact then
vi1.displayBox.setFocus
else
vi1.nickBox.setFocus; }
ForceForegroundWindow(vi1.Handle);
end;
end;
end
end;
clear;
end;
// auto-away (isHooked is needed for keyboard handling)
if IsHooked and Account.AccProto.IsOnline then
begin
// SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, @isSSActive, 0);
SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, @isSSRuning, 0);
Inc(autoaway.time, 5); // we are in delay-block then 0.5s
if IsMoved and not (autoaway.ss and (IsSSRuning or IsLocked)) and not (autoaway.boss and BossMode.isBossKeyOn) then
begin
autoaway.time := 0;
if (autoaway.autoexit) and (autoaway.triggered <> TR_NONE) then
ExitFromAutoaway;
end else if (autoaway.triggered = TR_NONE) and not (Account.AccProto.GetStatus in [Byte(SC_AWAY), Byte(SC_NA)]) or
(autoaway.triggered <> TR_NONE) then
begin
if autoaway.away and (autoaway.time >= autoaway.awayTime) and (autoaway.triggered = TR_NONE) then
begin
if autoaway.setxstatus then
begin
autoaway.bakxstatus := Account.AccProto.GetXStatus;
Account.AccProto.CurXStatus := autoaway.xstatus;
end;
autoaway.bakstatus := Account.AccProto.SetStatus(Byte(SC_AWAY), True);
autoaway.triggered := TR_AWAY; // has to be set AFTER setstatus
end;
if (autoaway.na and (autoaway.time >= autoaway.naTime) and (autoaway.triggered <> TR_NA)) or
(autoaway.ss and (isSSRuning or isLocked)) or (autoaway.boss and BossMode.isBossKeyOn) then
begin
if autoaway.triggered = TR_NONE then
begin
if autoaway.setxstatus then
begin
autoaway.bakxstatus := Account.AccProto.GetXStatus;
Account.AccProto.CurXStatus := autoaway.xstatus;
end;
autoaway.bakstatus := Account.AccProto.SetStatus(Byte(SC_NA), True);
end else
Account.AccProto.SetStatus(Byte(SC_NA));
autoaway.triggered := TR_NA; // has to be set AFTER setstatus
end;
end;
end;
if appBarResizeDelayed then
begin
appBarResizeDelayed := False;
if docking.appBar then
utilLib.setAppBarSize;
end;
Self.DoAutosize;
if dbUpdateDelayed then
begin
dbUpdateDelayed := False;
incDBTimer;
if Assigned(RnQdbFrm) AND (RnQdbFrm.Handle <> 0) then
RnQdbFrm.updateList;
end;
end; // short delay
// update noincomingcounter
if NoIncomingCounter > 0 then
Dec(NoIncomingCounter);
chatFrm.chats.CheckTypingTimeAll;
// apply alwaysOnTop
if formVisible(Self) and (alwaysOnTop <> isTopMost(Self)) then
setTopMost(Self, alwaysOnTop);
if formVisible(chatFrm) and (chatAlwaysOnTop <> isTopMost(chatFrm)) then
setTopMost(chatFrm, chatAlwaysOnTop);
TipsShowTop;
if MustQuit then
quit;
end; // OnTimer
//procedure TRnQmain.rosterDragOver(Sender: TBaseVirtualTree; Source: TObject; Shift: TShiftState; State: TDragState; Pt: TPoint;
// Mode: TDropMode; var Effect: Integer; var Accept: Boolean);
//var
// dest, destGrp, destDiv, clickedGrp, clickedDiv: Tnode;
//begin
// Accept := False;
// if not Sender.equals(Source) then
// Exit;
// dest := roasterLib.nodeAt(Pt.X, Pt.Y);
// if dest = nil then
// Exit;
// case dest.kind of
// NODE_CONTACT:
// begin
// destGrp := dest.parent;
// if destGrp.kind = NODE_GROUP then // it's not sure that contact is under a group
// destDiv := destGrp.parent
// else
// begin
// destDiv := destGrp;
// destGrp := nil;
// end;
// end;
// NODE_GROUP:
// begin
// destGrp := dest;
// destDiv := destGrp.parent;
// end;
// NODE_DIV:
// begin
// destGrp := nil;
// destDiv := dest;
// end;
// else
// begin // should never reach this
// msgDlg('error: drag over: unknown kind', TRUE, mtError);
// Exit;
// end;
// end;
// if Assigned(clickedContact) then
// begin
// clickedGrp := Tnode(TCE(clickedContact.data^).Node).parent;
// if clickedGrp.kind = NODE_DIV then
// begin
// clickedDiv := clickedGrp;
// clickedGrp := nil;
// end
// else
// clickedDiv := clickedGrp.parent;
// Accept := (clickedDiv = destDiv) and Assigned(clickedContact) and (clickedGrp <> destGrp);
// if Accept then
// if not clickedContact.CntIsLocal and (Account.AccProto.IsOffline or not Assigned(destGrp) or not groups.Exists(destGrp.groupId)) then
// Accept := False;
// end else if Assigned(clickedNode) and (clickedNode.groupId > 0) then
// begin
// if Assigned(clickedNode) and not (clickedNode.parent = nil) and (clickedNode.parent.kind = NODE_DIV) then
// clickedDiv := clickedNode.parent
// else
// clickedDiv := nil;
// Accept := ((dest.kind = NODE_GROUP) and (clickedNode.groupId <> destGrp.groupId)) or ((dest.kind = NODE_DIV) and (clickedDiv = destDiv))
// end
//end;
//procedure TRnQmain.rosterDragDrop(Sender: TBaseVirtualTree; Source: TObject; DataObject: IDataObject; Formats: TFormatArray;
// Shift: TShiftState; Pt: TPoint; var Effect: Integer; Mode: TDropMode);
//var
// grpOrDiv, n: Tnode;
// o: Integer;
//begin
// if not Sender.equals(Source) then
// Exit;
//
// roasterLib.dragging := False;
// grpOrDiv := roasterLib.nodeAt(Pt.X, Pt.Y);
// while grpOrDiv.kind = NODE_CONTACT do
// grpOrDiv := grpOrDiv.parent;
// if Assigned(clickedContact) then
// SetNewGroupFor(clickedContact, RDUtils.ifThen(grpOrDiv.kind = NODE_GROUP, grpOrDiv.groupId));
// if Assigned(clickedNode) and (clickedNode.groupId > 0) then
// begin
// n := grpOrDiv;
// if n.kind = NODE_DIV then // we want the group to be the first
// begin
// // n = first group on this div
// n := n.firstChild;
// repeat
// n := n.next;
// if n = nil then
// Exit;
// until n.kind = NODE_GROUP;
// groups.SetOrder(clickedNode.groupId, n.order - 1);
// end
// else
// begin
// // is this the last group?
// repeat
// n := n.next
// until (n = nil) or (n.kind = NODE_GROUP);
// if n = nil then
// // we want the group to be the last
// groups.SetOrder(clickedNode.groupId, grpOrDiv.order + 1)
// else
// begin
// n := grpOrDiv;
// o := n.order - 1;
// groups.SetOrder(clickedNode.groupId, o);
// repeat
// if n.groupID <> clickedNode.groupId then
// begin
// dec(o);
// groups.SetOrder(n.groupId, o);
// end;
// n := n.prev;
// until (n = nil) or (n.kind <> NODE_GROUP);
// end;
// end;
// rosterRebuildDelayed := True;
// end;
//end;
procedure TRnQmain.FormCreate(Sender: TObject);
begin
uninstallHook;
installHook(Self.Handle);
Width := 120;
// contactsPnl:=sbar.panels[0];
Application.OnActivate := AppActivate;
Application.OnDeactivate := AppActivate;
{ Let Windows know we accept dropped files }
DragAcceptFiles(Self.Handle, TRUE);
// Application.OnMessage := AppMessage;
oldHandle := 0;
MainFormHandleUpdate;
FToggling := False;
LastMonCnt := GetActiveMonitorCount;
SaveFormPositionForCurrentMonitorCount;
CLBox := nil;
end;
procedure TRnQmain.InitDocument;
begin
if not Assigned(CLBox) then
begin
CLBox := TCLBox.Create(Self);
CLBox.Enabled := False;
CLBox.Align := alClient;
// CLBox.Width := 0;
// CLBox.Height := 0;
// CLBox.OnDragOver := chatDragOver;
// CLBox.OnDragDrop := chatDragDrop;
CLBox.OnKeyDown := CLKeyDown;
CLBox.Load;
end;
CLBox.ClearCL;
CLBox.InitSettings;
CLBox.InitMenus;
CLBox.ApplySystemColor;
CLBox.Enabled := True;
end;
procedure TRnQmain.UpdateContactCount;
begin
CLBox.UpdateContactCount;
end;
procedure TRnQmain.CLKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Shift = [] then
case Key of
// VK_HOME, VK_END, VK_PRIOR, VK_NEXT, VK_UP, VK_DOWN, VK_RIGHT, VK_LEFT:
// VK_DELETE:
VK_F2:
if not (clickedNode = nil) then
if clickedNode.kind = NODE_GROUP then
begin
if not groups.Get(clickedNode.groupId).IsLocal and not Account.AccProto.IsOnline then
begin
MsgDlg('Group is not local and must be modified while online', True, mtInformation);
Exit;
end;
CLBox.EditNode(clickedNode, GA_Rename)
end else
CLBox.EditNode(clickedNode);
VK_F3:
chatFrm.flash();
VK_APPS:
CLBox.OpenContextMenu;
end;
if Shift = [ssShift] then
case Key of
VK_F10:
CLBox.OpenContextMenu;
end;
FormKeyDown(Sender, Key, Shift);
end;
//procedure TRnQmain.rosterMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
//begin
// if (ssLeft in Shift) and ((clickedContact <> nil) or (clickedNode.groupId > 0)) then
// begin
// roasterLib.dragging := TRUE;
//// roster.BeginDrag(False);
// end;
//end;
//// Mute
//// Exec
// if Assigned(Account.AccProto) and Assigned(clickedContact) then
// Account.AccProto.SetMuted(clickedContact, not clickedContact.IsMuted);
//
//// Update
// TAction(Sender).Visible := False; Exit; // Unused
//
// if not Assigned(clickedContact) then
// Exit;
//
// TAction(Sender).Visible := not (clickedContact.UID2Cmp = spamsFilename);
// TAction(Sender).Enabled := Account.AccProto.IsOnline;
//
// if clickedContact.IsMuted then
// begin
// TAction(Sender).HelpKeyword := 'unmuted';
// TAction(Sender).Caption := GetTranslation('Unmute');
// end
// else
// begin
// TAction(Sender).HelpKeyword := 'muted';
// TAction(Sender).Caption := GetTranslation('Mute');
// end;
// if OnlFeature(Account.AccProto) then
// Account.AccProto.RemoveMeFromHisCL(clickedContact.uid)
procedure TRnQmain.CMMouseEnter(var Msg: TMessage);
begin
inherited;
if (Pointer(Msg.LParam) = Pointer(RnQmain)) or (Pointer(Msg.LParam) = Pointer(RnQmain.CLBox)) then
if (transparency.chgOnMouse) and not FMouseInControl then
begin
if AlphaBlend then
AlphaBlendValue := transparency.active;
FMouseInControl := True;
end;
end;
procedure TRnQmain.CMMouseLeave(var Msg: TMessage);
begin
inherited;
if (Pointer(Msg.LParam) = Pointer(RnQmain)) or (Pointer(Msg.LParam) = Pointer(RnQmain.CLBox)) then
if (transparency.chgOnMouse) and FMouseInControl then
begin
if AlphaBlend then
if Handle <> getForegroundWindow then
AlphaBlendValue := transparency.inactive;
FMouseInControl := False;
end;
end;
procedure TRnQmain.WMNCActivate(var Msg: TWMNCActivate);
begin
inherited;
ApplyTransparency;
if Assigned(CLBox) then
CLBox.FocusChanged(Msg.Active); // RnQmain.Handle = GetForegroundWindow
end;
{ procedure TRnQmain.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
with Params do
begin
// Style := Style and (not WS_CAPTION);
// Style := Style and not WS_OVERLAPPEDWINDOW or WS_BORDER and (not WS_CAPTION);
Style := (Style or WS_POPUP) and (not WS_DLGFRAME);
// Style := Style or WS_SYSMENU;
// ExStyle := ExStyle or WS_EX_APPWINDOW or WS_EX_NOPARENTNOTIFY;
end;
end;
}
procedure TRnQmain.onCloseSomeWindows(Sender: TObject; var Action: TCloseAction);
begin
Inherited;
Action := caFree;
end;
procedure TRnQmain.previewFormKeyPress(Sender: TObject; var Key: Char);
begin
case Key of
#27:
begin
(Sender as TForm).Close;
Key := #0;
end;
end;
end;
procedure TRnQmain.MemoKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if (Sender is TMemo) then
begin
if (Key = $41) and (ssCtrl in Shift) then
TMemo(Sender).SelectAll
end else
inherited;
end;
procedure TRnQmain.ReStart(Sender: TObject);
begin
try
quitUser;
if Assigned(StatusIcon) then
begin
if Assigned(StatusIcon.TrayIcon) then
StatusIcon.TrayIcon.Hide;
StatusIcon.Empty;
end;
except
end;
RQUtil.restartApp;
end;
// TODO: Plugin menu items
// function TRnQmain.AddMainMenuItem(wPar: WPARAM; lPar: LPARAM): Integer; cdecl;
function TRnQmain.AddContactMenuItem(pMI: PCLISTMENUITEM): Integer; // cdecl;
{ function TRnQmain.AddContactMenuItem(pPluginProc : Pointer; menuIcon: hIcon; menuCaption:String;
menuHint:string; //procIdx : Integer;
position : Integer;
PopupName : String; popupPosition : Integer;
hotKey : DWORD; PicName : String = ''):integer; }
var
// clMI : TCLISTMENUITEM;
str, Str1: String;
i: Integer;
MI: TRQMenuItem;
PM: TRQMenuItem;
MM: TMenuItem;
// Ic : TIcon;
// bmp : TBitmap;
begin
// // Str :=String(wPar);
// // clMI := PCLISTMENUITEM(lPar)^;
// if pMI.cbSize <> sizeof(TCLISTMENUITEM) then
// begin
// Result := 0;
// Exit;
// end;
// // Str := pMI.pszName;
// MI := TRQMenuItem.Create(Self);
// MI.caption := UnUTF(pMI.pszName);
// MI.Hint := UnUTF(pMI.pszHint);
// if (pMI.hIcon <> 0) then
// begin
// ico2bmp2(pMI.hIcon, MI.Bitmap);
// end;
// // MI.ServiceName := clMI.pszService;
// MI.PluginProc := pMI.Proc;
// // MI.Plugin := pPlugin;
// // MI.ProcIdx := procIdx;
// if pMI.Proc = NIL then
// MI.OnClick := NIL
// else
// MI.OnClick := OnPluginMenuClick;
// MI.ImageName := pMI.pszPic;
// MI.Enabled := (pMI.flags and RQFM_DISABLED) = 0;
// MI.visible := (pMI.flags and RQFM_HIDDEN) = 0;
// MM := contactMenu.Items;
// str := UnUTF(pMI.pszPopupName);
// if str <> '' then
// begin
// Str1 := str;
// while str > '' do
// begin
// i := pos('\', str);
// if i = 0 then
// i := length(str) + 1;
// Str1 := copy(str, 1, i - 1);
// delete(str, 1, i + length('\') - 1);
// if Assigned(MM.Find(Str1)) then
// MM := TMenuItem(MM.Find(Str1))
// else
// begin
// PM := TRQMenuItem.Create(contactMenu);
// PM.caption := Str1;
// MM.add(PM);
// MM := PM;
// // PM.Add(MI);
// end;
// end;
// end;
// // else
// // contactMenu.Items.Insert(12, MI);
// MM.add(MI);
// Result := MI.Handle;
end;
// function TRnQmain.UpdateContactMenuItem(menuHandle: hmenu; pMI : PCLISTMENUITEM ): Integer;// cdecl;
Procedure TRnQmain.UpdateContactMenuItem(menuHandle: hmenu; pMI: PCLISTMENUITEM); // cdecl;
function findItem(item: TMenuItem): TMenuItem;
var
i: Integer;
begin
Result := NIL;
if item.Handle = menuHandle then
Result := item
else if item.Count > 0 then
for i := 0 to item.Count - 1 do
begin
// if item.Items[i].Count > 0 then
Result := findItem(item.Items[i]);
if Result <> NIL then
break;
end;
end;
var
MI: TMenuItem;
begin
// MI := findItem(contactMenu.Items);
// if MI <> NIL then
// begin
// if (pMI.flags and RQFM_UPD_CAPTION) > 0 then
// MI.caption := UnUTF(pMI.pszName);
// if (pMI.flags and RQFM_UPD_HINT) > 0 then
// MI.Hint := UnUTF(pMI.pszHint);
// if (pMI.flags and RQFM_UPD_ENABLE) > 0 then
// MI.Enabled := (pMI.flags and RQFM_DISABLED) = 0;
// if (pMI.flags and RQFM_UPD_VISIBLE) > 0 then
// MI.visible := (pMI.flags and RQFM_HIDDEN) = 0;
// if (pMI.flags and RQFM_UPD_ICON) > 0 then
// if (pMI.hIcon <> 0) then
// ico2bmp2(pMI.hIcon, MI.Bitmap)
// else
// begin
// MI.Bitmap := NIL; // .Empty := True;
// end;
// end;
// // Result := mi
end;
procedure TRnQmain.DelContactMenuItem(menuHandle: hmenu);
function findItem(item: TMenuItem): TMenuItem;
var
i: Integer;
begin
Result := NIL;
if item.Handle = menuHandle then
Result := item
else if item.Count > 0 then
for i := 0 to item.Count - 1 do
begin
// if item.Items[i].Count > 0 then
Result := findItem(item.Items[i]);
if Result <> NIL then
break;
end;
end;
var
item, parItem: TMenuItem;
begin
// item := findItem(contactMenu.Items);
// if item <> NIL then
// begin
// parItem := item.parent;
// parItem.remove(item);
// item.free;
// while (parItem <> contactMenu.Items) and (parItem.Count = 0) do
// begin
// item := parItem;
// parItem := item.parent;
// parItem.remove(item);
// item.free;
// end;
// end;
end;
procedure TRnQmain.OnPluginMenuClick(Sender: TObject);
var
// pr : procedure(uid:String);
pr: procedure(uid: RawByteString);
begin
if Sender is TRQMenuItem then
begin
if TRQMenuItem(Sender).PluginProc <> NIL then
// if (TRQMenuItem(Sender).Plugin^) is Tplugin then
begin
pr := TRQMenuItem(Sender).PluginProc;
pr(clickedContact.UID2cmp);
// Tplugin(TRQMenuItem(Sender).Plugin).cast(
// char(PM_EVENT)+char(PE_CONTACTMENUCLICK)+_int(TRQMenuItem(Sender).ProcIdx)+_int(StrToIntDef(clickedContact.UID, 0))
// )
end;
end;
end;
procedure TRnQmain.OnTrayEvent(Sender: TObject; ev: TTrayEvent);
begin
if not locked and running then
case ev of
TE_CLICK:
begin
if (not useSingleClickTray)
// or (useSingleClickTray and RnQmain.Visible and not alwaysOnTop and not (RnQmain.handle=getForegroundWindow))
then
SetForegroundWindow(self.Handle)
else
begin
// mainfrm.toggleVisible
// if not mainFrm.Visible then
// mainFrm.toggleVisible;
trayAction;
end;
end;
TE_2CLICK: if (not useSingleClickTray) then trayAction;
TE_RCLICK:
if GetAsyncKeyState(VK_CONTROL) shr 7 <> 0 then
eventQ.clear
else
begin
ForceForegroundWindow(Self.Handle);
CLBox.OpenMainMenuDelayed;
end;
end;
end;
procedure TRnQmain.WMRestoreApp(var Msg: TMessage);
begin
if IsIconic(Application.Handle) then
Application.Restore
else
Application.BringToFront;
end;
procedure TRnQmain.DefaultHandler(var Message);
var
Len: Integer;
Data: String;
begin
with TMessage(Message) do
if Msg = WM_FINDINSTANCE then
begin
Result := 1337;
end else if Msg = WM_HANDLEICQLINK then
begin
SetLength(Data, MAX_PATH);
Len := GlobalGetAtomName(WPARAM, PChar(Data), MAX_PATH);
GlobalDeleteAtom(WPARAM);
SetLength(Data, Len);
ProcessICQLink(Data);
end else inherited DefaultHandler(message);
end;
procedure TRnQmain.StopTimer(ID: Integer);
begin
if HandleAllocated then
KillTimer(Handle, ID);
end;
procedure TRnQmain.StartTimer(ID, Time: Integer);
begin
if HandleAllocated then
SetTimer(Handle, ID, Time, nil);
end;
initialization
WM_FINDINSTANCE := RegisterWindowMessage('Unique R&Q message');
MonPositions := TDictionary.Create;
finalization
FreeAndNil(MonPositions);
end.