1 Star 0 Fork 0

Yongbo/winauth

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
AuthenticatorListBox.cs 62.10 KB
一键复制 编辑 原始数据 按行查看 历史
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074
/*
* Copyright (C) 2013 Colin Mackie.
* This software is distributed under the terms of the GNU General Public License.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using WinAuth.Resources;
using System.Diagnostics;
namespace WinAuth
{
/// <summary>
/// An item within the OwnerDraw list that represents an authenticator
/// </summary>
public class AuthenticatorListitem
{
/// <summary>
/// Create a new AuthenticatorListitem
/// </summary>
/// <param name="auth">authenticator</param>
/// <param name="index">index of item</param>
public AuthenticatorListitem(WinAuthAuthenticator auth, int index)
{
Authenticator = auth;
LastUpdate = DateTime.MinValue;
Index = index;
DisplayUntil = DateTime.MinValue;
}
/// <summary>
/// Index of item in list
/// </summary>
public int Index { get; set; }
/// <summary>
/// Authenticator wrapper
/// </summary>
public WinAuthAuthenticator Authenticator { get; set; }
/// <summary>
/// When the item was last updated
/// </summary>
public DateTime LastUpdate { get; set;}
/// <summary>
/// When the code should be displayed to if not AutoRefresh
/// </summary>
public DateTime DisplayUntil { get; set; }
/// <summary>
/// The last code to be displayed
/// </summary>
public string LastCode { get; set; }
/// <summary>
/// If this item is being dragged
/// </summary>
public bool Dragging { get; set; }
/// <summary>
/// A count for password protected to allow multipel unprotect operations
/// </summary>
public int UnprotectCount { get; set; }
/// <summary>
/// Width of item for autosizing
/// </summary>
public int AutoWidth { get; set; }
}
/// <summary>
/// Delegate for event when item is removed
/// </summary>
/// <param name="source"></param>
/// <param name="args"></param>
public delegate void AuthenticatorListItemRemovedHandler(object source, AuthenticatorListItemRemovedEventArgs args);
/// <summary>
/// Delegate for Redordered event
/// </summary>
/// <param name="source"></param>
/// <param name="args"></param>
public delegate void AuthenticatorListReorderedHandler(object source, AuthenticatorListReorderedEventArgs args);
/// <summary>
/// Event arguments for removing an item
/// </summary>
public class AuthenticatorListItemRemovedEventArgs : EventArgs
{
/// <summary>
/// The item that was removed
/// </summary>
public AuthenticatorListitem Item { get; private set; }
/// <summary>
/// Default constructor
/// </summary>
public AuthenticatorListItemRemovedEventArgs(AuthenticatorListitem item)
: base()
{
Item = item;
}
}
/// <summary>
/// Event arguments for reordering the list
/// </summary>
public class AuthenticatorListReorderedEventArgs : EventArgs
{
/// <summary>
/// Default constructor
/// </summary>
public AuthenticatorListReorderedEventArgs()
: base()
{
}
}
/// <summary>
/// Delegate for event when double click
/// </summary>
/// <param name="source"></param>
/// <param name="args"></param>
public delegate void AuthenticatorListDoubleClickHandler(object source, AuthenticatorListDoubleClickEventArgs args);
/// <summary>
/// Event arguments for double click
/// </summary>
public class AuthenticatorListDoubleClickEventArgs : EventArgs
{
public WinAuthAuthenticator Authenticator;
/// <summary>
/// Default constructor
/// </summary>
public AuthenticatorListDoubleClickEventArgs(WinAuthAuthenticator auth)
: base()
{
Authenticator = auth;
}
}
/// <summary>
/// An owner draw listbox that displays wrapped authenticators
/// </summary>
public class AuthenticatorListBox : ListBox
{
private const int MARGIN_LEFT = 4;
private const int MARGIN_TOP = 8;
private const int MARGIN_RIGHT = 8;
private const int ICON_WIDTH = 48;
private const int ICON_HEIGHT = 48;
private const int ICON_MARGIN_RIGHT = 12;
private const int LABEL_MARGIN_BOTTOM = 4;
private const int LABEL_WIDTH = 250;
private const int FONT_SIZE = 12;
private const int PIE_WIDTH = 46;
private const int PIE_HEIGHT = 46;
private const int PIE_MARGIN = 2;
private const int PIE_STARTANGLE = 270;
private const int PIE_SWEEPANGLE = 360;
/// <summary>
/// Event handler for ItemRemoved
/// </summary>
public event AuthenticatorListItemRemovedHandler ItemRemoved;
/// <summary>
/// Event handler for Reordered
/// </summary>
public event AuthenticatorListReorderedHandler Reordered;
/// <summary>
/// Scrolled event handler
/// </summary>
[Category("Action")]
public event ScrollEventHandler Scrolled = null;
/// <summary>
/// Event handler for double click
/// </summary>
public new event AuthenticatorListDoubleClickHandler DoubleClick;
/// <summary>
/// Rename textbox
/// </summary>
private TextBox _renameTextbox;
/// <summary>
/// Current item
/// </summary>
private AuthenticatorListitem _currentItem;
/// <summary>
/// Saved point of mouse down
/// </summary>
private Point _mouseDownLocation = Point.Empty;
/// <summary>
/// Saved pont of mouse move
/// </summary>
private Point _mouseMoveLocation = Point.Empty;
/// <summary>
/// Bitmap of cloned item we are dragging
/// </summary>
private Bitmap _draggedBitmap;
/// <summary>
/// Item that is being dragged
/// </summary>
private AuthenticatorListitem _draggedItem;
/// <summary>
/// Offset of last position of dragged bitmap so we can paint behind it
/// </summary>
private Rectangle _draggedBitmapRect;
/// <summary>
/// Offset of mouseY and top of item
/// </summary>
private int _draggedBitmapOffsetY;
/// <summary>
/// Last TopIndex if we scrolled while dragging
/// </summary>
private int? _lastDragTopIndex;
/// <summary>
/// When we last changed the TopIndex
/// </summary>
private DateTime _lastDragScroll;
/// <summary>
/// Default constructor for our authenticator list box
/// </summary>
public AuthenticatorListBox()
{
// set owner draw stlying
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true);
this.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
this.ReadOnly = true;
this.AllowDrop = true;
this.DoubleBuffered = true;
// hook the scroll event
this.Scrolled += AuthenticatorListBox_Scrolled;
// hook the context menu
this.ContextMenuStrip = new ContextMenuStrip();
this.ContextMenuStrip.Opening += ContextMenuStrip_Opening;
// preload the content menu
loadContextMenuStrip();
}
/// <summary>
/// Capture the mouse wheel events and scroll to appropriate position
/// </summary>
/// <param name="e"></param>
protected override void OnMouseWheel(MouseEventArgs e)
{
base.OnMouseWheel(e);
int y = (e.Delta * this.ItemHeight) + MARGIN_TOP;
ScrollEventArgs sargs = new ScrollEventArgs(ScrollEventType.ThumbPosition, y, ScrollOrientation.VerticalScroll);
Scrolled(this, sargs);
}
/// <summary>
/// Copy the current code when double-clicking
/// </summary>
/// <param name="e"></param>
protected override void OnMouseDoubleClick(MouseEventArgs e)
{
var item = this.CurrentItem;
if (item != null)
{
DoubleClick(this, new AuthenticatorListDoubleClickEventArgs(item.Authenticator));
}
}
#region Control Events
/// <summary>
/// Resize event to resize base and fix rename box location
/// </summary>
/// <param name="e"></param>
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
setRenameTextboxLocation();
}
/// <summary>
/// Fix position of rename box when scrolling
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void AuthenticatorListBox_Scrolled(object sender, ScrollEventArgs e)
{
if (e.Type == ScrollEventType.EndScroll || e.Type == ScrollEventType.ThumbPosition)
{
setRenameTextboxLocation();
}
}
/// <summary>
/// Click an item in the context menu
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void ContextMenu_Click(object sender, EventArgs e)
{
ProcessMenu((ToolStripItem)sender);
}
/// <summary>
/// Click to open the contxet menu and set the state
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void ContextMenuStrip_Opening(object sender, CancelEventArgs e)
{
SetContextMenuItems();
}
/// <summary>
/// Tick event used to update the pie, codes and relock authenticators
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void Tick(object sender, EventArgs e)
{
for (int index = 0; index < this.Items.Count; index++)
{
// get the item
AuthenticatorListitem item = this.Items[index] as AuthenticatorListitem;
WinAuthAuthenticator auth = item.Authenticator;
int y = (this.ItemHeight * index) - (this.TopIndex * this.ItemHeight);
if (auth.AutoRefresh == true)
{
// for autorefresh we repaint the pie or the code too
//int tillUpdate = (int)((auth.AuthenticatorData.ServerTime % ((long)auth.AuthenticatorData.Period * 1000L)) / 1000L);
int tillUpdate = (int)Math.Round((decimal)((auth.AuthenticatorData.ServerTime % ((long)auth.AuthenticatorData.Period * 1000L)) / 1000L) * (360M / (decimal)auth.AuthenticatorData.Period));
if (item.LastUpdate == DateTime.MinValue || tillUpdate == 0)
{
this.Invalidate(new Rectangle(0, y, this.Width, this.ItemHeight), false);
item.LastUpdate = DateTime.Now;
}
else
{
this.Invalidate(new Rectangle(0, y, this.Width, this.ItemHeight), false);
item.LastUpdate = DateTime.Now;
}
}
else
{
// check if we need to redraw
if (item.DisplayUntil != DateTime.MinValue)
{
// clear the item
if (item.DisplayUntil <= DateTime.Now)
{
item.DisplayUntil = DateTime.MinValue;
item.LastUpdate = DateTime.MinValue;
item.LastCode = null;
if (item.Authenticator.AuthenticatorData != null && item.Authenticator.AuthenticatorData.PasswordType == Authenticator.PasswordTypes.Explicit)
{
ProtectAuthenticator(item);
}
SetCursor(this.PointToClient(Control.MousePosition));
}
this.Invalidate(new Rectangle(0, y, this.Width, this.ItemHeight), false);
}
}
}
}
/// <summary>
/// Handle mouse down event
/// </summary>
/// <param name="e"></param>
protected override void OnMouseDown(MouseEventArgs e)
{
// set the current item based on position
SetCurrentItem(e.Location);
_mouseDownLocation = e.Location;
base.OnMouseDown(e);
}
/// <summary>
/// Handle the mouse up and check for click in the refresh icon
/// </summary>
/// <param name="e"></param>
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
if ((e.Button & System.Windows.Forms.MouseButtons.Left) != 0)
{
// if this was in a refresh icon, we do a refresh
int index = this.IndexFromPoint(e.Location);
if (index >= 0 && index < this.Items.Count)
{
var item = this.Items[index] as AuthenticatorListitem;
int x = 0;
int y = (this.ItemHeight * index) - (this.ItemHeight * this.TopIndex);
bool hasvscroll = (this.Height < (this.Items.Count * this.ItemHeight));
if (item.Authenticator.AutoRefresh == false && item.DisplayUntil < DateTime.Now
&& new Rectangle(x + this.Width - (ICON_WIDTH + MARGIN_RIGHT) - (hasvscroll ? SystemInformation.VerticalScrollBarWidth : 0), y + MARGIN_TOP, ICON_WIDTH, ICON_HEIGHT).Contains(e.Location))
{
if (UnprotectAuthenticator(item) == DialogResult.Cancel)
{
return;
}
item.LastCode = item.Authenticator.CurrentCode;
item.LastUpdate = DateTime.Now;
item.DisplayUntil = DateTime.Now.AddSeconds(10);
if (item.Authenticator.CopyOnCode == true)
{
// copy to clipboard
item.Authenticator.CopyCodeToClipboard(this.Parent as Form);
}
RefreshCurrentItem();
}
}
}
// dispose and reset the dragging
_mouseDownLocation = Point.Empty;
if (_draggedBitmap != null)
{
_draggedBitmap.Dispose();
_draggedBitmap = null;
this.Invalidate(_draggedBitmapRect);
}
if (_draggedItem != null)
{
_draggedItem = null;
}
}
/// <summary>
/// Handle the mouse move event to capture cursor position
/// </summary>
/// <param name="e"></param>
protected override void OnMouseMove(MouseEventArgs e)
{
_mouseMoveLocation = e.Location;
// if we are moving with LeftMouse down and moved more than 2 pixles then we are dragging
if (e.Button == System.Windows.Forms.MouseButtons.Left && _mouseDownLocation != Point.Empty && this.Items.Count > 1)
{
int dx = Math.Abs(_mouseDownLocation.X - e.Location.X);
int dy = Math.Abs(_mouseDownLocation.Y - e.Location.Y);
if (dx > 2 || dy > 2)
{
_draggedItem = this.CurrentItem;
// get a snapshot of the current item for the drag
bool hasvscroll = (this.Height < (this.Items.Count * this.ItemHeight));
_draggedBitmap = new Bitmap(this.Width - (hasvscroll ? SystemInformation.VerticalScrollBarWidth : 0), this.ItemHeight);
_draggedBitmapRect = Rectangle.Empty;
using (Graphics g = Graphics.FromImage(_draggedBitmap))
{
int y = (this.ItemHeight * this.CurrentItem.Index) - (this.ItemHeight * this.TopIndex);
Point screen = this.Parent.PointToScreen(new Point(this.Location.X, this.Location.Y + y));
g.CopyFromScreen(screen.X, screen.Y, 0, 0, new Size(this.Width - (hasvscroll ? SystemInformation.VerticalScrollBarWidth : 0), this.ItemHeight), CopyPixelOperation.SourceCopy);
// save offset in Y from top of item
_draggedBitmapOffsetY = e.Y - y;
}
// make the bitmap darker
Lighten(_draggedBitmap, -10);
_draggedItem.Dragging = true;
this.RefreshItem(_draggedItem);
// moved enough so start drag
this.DoDragDrop(_draggedItem, DragDropEffects.Move);
}
}
else if (e.Button == System.Windows.Forms.MouseButtons.None)
{
SetCursor(e.Location);
}
base.OnMouseMove(e);
}
/// <summary>
/// When we are dragging over
/// </summary>
/// <param name="e"></param>
protected override void OnDragOver(DragEventArgs e)
{
Rectangle screen = this.Parent.RectangleToScreen(new Rectangle(this.Location.X, this.Location.Y, this.Width, this.Height));
Point mousePoint = new Point(e.X, e.Y);
if (screen.Contains(mousePoint) == false)
{
e.Effect = DragDropEffects.None;
}
else if (_draggedBitmap != null)
{
e.Effect = DragDropEffects.Move;
using (Graphics g = this.CreateGraphics())
{
Point mouseClientPoint = this.PointToClient(mousePoint);
int x = 0;
int y = Math.Max(mouseClientPoint.Y - _draggedBitmapOffsetY, 0);
Rectangle rect = new Rectangle(x, y, _draggedBitmap.Width, _draggedBitmap.Height);
g.DrawImageUnscaled(_draggedBitmap, rect);
if (_draggedBitmapRect != Rectangle.Empty)
{
// invalidate the extent between the old rect and this one
Region region = new Region(rect);
region.Union(_draggedBitmapRect);
region.Exclude(rect);
this.Invalidate(region);
}
_draggedBitmapRect = rect;
}
}
}
/// <summary>
/// Check if we should continue dragging
/// </summary>
/// <param name="e"></param>
protected override void OnQueryContinueDrag(QueryContinueDragEventArgs e)
{
Rectangle screen = this.Parent.RectangleToScreen(new Rectangle(this.Location.X, this.Location.Y, this.Width, this.Height));
Point mousePoint = Cursor.Position;
// if ESC is pressed, always stop
if (e.EscapePressed == true || ((e.KeyState & 1) == 0 && screen.Contains(mousePoint) == false))
{
e.Action = DragAction.Cancel;
if (_draggedItem != null)
{
_draggedItem.Dragging = false;
this.RefreshItem(_draggedItem);
_draggedItem = null;
}
if (_draggedBitmap != null)
{
_draggedBitmap.Dispose();
_draggedBitmap = null;
this.Invalidate(_draggedBitmapRect);
}
_mouseDownLocation = Point.Empty;
}
else
{
DateTime now = DateTime.Now;
// if we are at the top or bottom, scroll every 150ms
if (mousePoint.Y >= screen.Bottom)
{
int visible = this.ClientSize.Height / this.ItemHeight;
int maxtopindex = Math.Max(this.Items.Count - visible + 1, 0);
if (this.TopIndex < maxtopindex && now.Subtract(_lastDragScroll).TotalMilliseconds >= 150)
{
this.TopIndex++;
_lastDragScroll = now;
this.Refresh();
}
}
else if (mousePoint.Y <= screen.Top)
{
int visible = this.ClientSize.Height / this.ItemHeight;
if (this.TopIndex > 0 && now.Subtract(_lastDragScroll).TotalMilliseconds >= 150)
{
this.TopIndex--;
_lastDragScroll = now;
this.Refresh();
}
}
_lastDragTopIndex = this.TopIndex;
base.OnQueryContinueDrag(e);
}
}
/// <summary>
/// When a dragdrop operation has completed
/// </summary>
/// <param name="e"></param>
protected override void OnDragDrop(DragEventArgs e)
{
AuthenticatorListitem item = e.Data.GetData(typeof(AuthenticatorListitem)) as AuthenticatorListitem;
if (item != null)
{
// stop paiting as we reorder to reduce flicker
WinAPI.SendMessage(this.Handle, WinAPI.WM_SETREDRAW, 0, IntPtr.Zero);
try
{
// get the new index
Point point = this.PointToClient(new Point(e.X, e.Y));
int index = this.IndexFromPoint(point);
if (index < 0)
{
index = this.Items.Count - 1;
}
// move the item
this.Items.Remove(item);
this.Items.Insert(index, item);
// set the correct indexes of our items
for (int i = 0; i < this.Items.Count; i++)
{
(this.Items[i] as AuthenticatorListitem).Index = i;
}
// fire the reordered event
Reordered(this, new AuthenticatorListReorderedEventArgs());
// clear state
item.Dragging = false;
_draggedItem = null;
if (_draggedBitmap != null)
{
_draggedBitmap.Dispose();
_draggedBitmap = null;
}
if (_lastDragTopIndex != null)
{
this.TopIndex = _lastDragTopIndex.Value;
}
}
finally
{
// resume painting
WinAPI.SendMessage(this.Handle, WinAPI.WM_SETREDRAW, 1, IntPtr.Zero);
}
this.Refresh();
}
else
{
base.OnDragDrop(e);
}
}
/// <summary>
/// Main WndProc handler to capture scroll events
/// </summary>
/// <param name="msg"></param>
protected override void WndProc(ref System.Windows.Forms.Message msg)
{
if (msg.Msg == WinAPI.WM_VSCROLL)
{
if (Scrolled != null)
{
WinAPI.ScrollInfoStruct si = new WinAPI.ScrollInfoStruct();
si.fMask = WinAPI.SIF_ALL;
si.cbSize = Marshal.SizeOf(si);
WinAPI.GetScrollInfo(msg.HWnd, 0, ref si);
if (msg.WParam.ToInt32() == WinAPI.SB_ENDSCROLL)
{
ScrollEventArgs sargs = new ScrollEventArgs(ScrollEventType.EndScroll, si.nPos);
Scrolled(this, sargs);
}
else if (msg.WParam.ToInt32() == WinAPI.SB_THUMBTRACK)
{
ScrollEventArgs sargs = new ScrollEventArgs(ScrollEventType.ThumbTrack, si.nPos);
Scrolled(this, sargs);
}
}
}
base.WndProc(ref msg);
}
#endregion
#region Item renaming
/// <summary>
/// Set the position of the rename textbox
/// </summary>
private void setRenameTextboxLocation()
{
if (_renameTextbox != null && _renameTextbox.Visible == true)
{
AuthenticatorListitem item = _renameTextbox.Tag as AuthenticatorListitem;
if (item != null)
{
int y = (this.ItemHeight * item.Index) - (this.TopIndex * this.ItemHeight) + MARGIN_TOP;
if (RenameTextbox.Location.Y != y)
{
RenameTextbox.Location = new Point(RenameTextbox.Location.X, y);
}
Refresh();
}
}
}
/// <summary>
/// Get or create the rename textbox
/// </summary>
public TextBox RenameTextbox
{
get
{
bool hasvscroll = (this.Height < (this.Items.Count * this.ItemHeight));
int labelMaxWidth = GetMaxAvailableLabelWidth(this.Width - this.Margin.Horizontal - this.DefaultPadding.Horizontal - (hasvscroll ? SystemInformation.VerticalScrollBarWidth : 0));
if (_renameTextbox == null)
{
_renameTextbox = new TextBox();
_renameTextbox.Name = "renameTextBox";
_renameTextbox.AllowDrop = true;
_renameTextbox.CausesValidation = false;
_renameTextbox.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
_renameTextbox.Location = new System.Drawing.Point(0, 0);
_renameTextbox.Multiline = false;
_renameTextbox.Name = "secretCodeField";
_renameTextbox.Size = new System.Drawing.Size(labelMaxWidth, 22);
_renameTextbox.TabIndex = 0;
_renameTextbox.Visible = false;
_renameTextbox.Leave += RenameTextbox_Leave;
_renameTextbox.KeyPress += _renameTextbox_KeyPress;
this.Controls.Add(_renameTextbox);
}
else
{
_renameTextbox.Width = labelMaxWidth;
}
return _renameTextbox;
}
}
/// <summary>
/// Get flag is we are renaming
/// </summary>
public bool IsRenaming
{
get
{
return (RenameTextbox.Visible == true);
}
}
/// <summary>
/// End the renaming and decide to save
/// </summary>
/// <param name="save"></param>
public void EndRenaming(bool save = true)
{
if (save == false)
{
RenameTextbox.Tag = null;
}
RenameTextbox.Visible = false;
}
/// <summary>
/// Keypress event to cancel or commit renaming
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void _renameTextbox_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 27)
{
RenameTextbox.Tag = null;
RenameTextbox.Visible = false;
e.Handled = true;
}
else if (e.KeyChar == 13 || e.KeyChar == 9)
{
RenameTextbox.Visible = false;
e.Handled = true;
}
}
/// <summary>
/// Handle the focus leave for rename box
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void RenameTextbox_Leave(object sender, EventArgs e)
{
RenameTextbox.Visible = false;
AuthenticatorListitem item = RenameTextbox.Tag as AuthenticatorListitem;
if (item != null)
{
string newname = RenameTextbox.Text.Trim();
if (newname.Length != 0)
{
// force the autowidth to be recaculated when we set the name
item.AutoWidth = 0;
item.Authenticator.Name = newname;
RefreshItem(item.Index);
}
}
}
#endregion
#region Public Properties
/// <summary>
/// Readonly flag
/// </summary>
public bool ReadOnly { get; set; }
/// <summary>
/// The current (selected) authenticator
/// </summary>
public AuthenticatorListitem CurrentItem
{
get
{
if (_currentItem == null && this.Items.Count != 0)
{
_currentItem = (AuthenticatorListitem)this.Items[0];
}
return _currentItem;
}
set
{
_currentItem = value;
}
}
#endregion
#region Private methods
/// <summary>
/// Set the current item based on the mouse position
/// </summary>
/// <param name="mouseLocation">mouse position</param>
private void SetCurrentItem(Point mouseLocation)
{
int index = this.IndexFromPoint(mouseLocation);
if (index < 0)
{
index = 0;
}
else if (index >= this.Items.Count)
{
index = this.Items.Count - 1;
}
if (index >= this.Items.Count)
{
CurrentItem = null;
}
else
{
CurrentItem = this.Items[index] as AuthenticatorListitem;
}
}
/// <summary>
/// Set the current cursor based on position
/// </summary>
/// <param name="mouseLocation">current mouse position</param>
private void SetCursor(Point mouseLocation, Cursor force = null)
{
// set cursor if we are over a refresh icon
var cursor = Cursor.Current;
if (force == null)
{
int index = this.IndexFromPoint(mouseLocation);
if (index >= 0 && index < this.Items.Count)
{
var item = this.Items[index] as AuthenticatorListitem;
int x = 0;
int y = (this.ItemHeight * index) - (this.TopIndex * this.ItemHeight);
bool hasvscroll = (this.Height < (this.Items.Count * this.ItemHeight));
if (item.Authenticator.AutoRefresh == false && item.DisplayUntil < DateTime.Now
&& new Rectangle(x + this.Width - (ICON_WIDTH + MARGIN_RIGHT) - (hasvscroll ? SystemInformation.VerticalScrollBarWidth : 0), y + MARGIN_TOP, ICON_WIDTH, ICON_HEIGHT).Contains(mouseLocation))
{
cursor = Cursors.Hand;
}
}
}
else
{
cursor = force;
}
if (Cursor.Current != cursor)
{
Cursor.Current = cursor;
}
}
/// <summary>
/// Unprotected an authenticator (if possible)
/// </summary>
/// <param name="item">item to unprotect</param>
/// <param name="screen">screen to display dialog for multi-monitors</param>
/// <returns></returns>
private DialogResult UnprotectAuthenticator(AuthenticatorListitem item, Screen screen = null)
{
// keep a count so we can have multiples
if (item.UnprotectCount > 0)
{
item.UnprotectCount++;
return DialogResult.OK;
}
// if there is no protection return None
WinAuthAuthenticator auth = item.Authenticator;
if (auth.AuthenticatorData == null || auth.AuthenticatorData.RequiresPassword == false)
{
return DialogResult.None;
}
// request the password
UnprotectPasswordForm getPassForm = new UnprotectPasswordForm();
getPassForm.Authenticator = auth;
if (screen != null)
{
// center on the current windows screen (in case of multiple monitors)
getPassForm.StartPosition = FormStartPosition.Manual;
int left = (screen.Bounds.Width / 2) - (getPassForm.Width / 2) + screen.Bounds.Left;
int top = (screen.Bounds.Height / 2) - (getPassForm.Height / 2) + screen.Bounds.Top;
getPassForm.Location = new Point(left, top);
}
else
{
getPassForm.StartPosition = FormStartPosition.CenterScreen;
}
DialogResult result = getPassForm.ShowDialog(this.Parent as Form);
if (result == DialogResult.OK)
{
item.UnprotectCount++;
}
return result;
}
/// <summary>
/// Reprotect the authenticator and each action or when the 30second window has expired
/// </summary>
/// <param name="item"></param>
private void ProtectAuthenticator(AuthenticatorListitem item)
{
// if already protected just decrement counter
item.UnprotectCount--;
if (item.UnprotectCount > 0)
{
return;
}
// reprotect the authenticator
WinAuthAuthenticator auth = item.Authenticator;
if (auth.AuthenticatorData == null)
{
return;
}
auth.AuthenticatorData.Protect();
item.UnprotectCount = 0;
}
/// <summary>
/// Preload the context menu items
/// </summary>
private void loadContextMenuStrip()
{
this.ContextMenuStrip.Items.Clear();
ToolStripLabel label = new ToolStripLabel();
label.Name = "contextMenuItemName";
label.ForeColor = SystemColors.HotTrack;
this.ContextMenuStrip.Items.Add(label);
this.ContextMenuStrip.Items.Add(new ToolStripSeparator());
//
EventHandler onclick = new EventHandler(ContextMenu_Click);
//
ToolStripMenuItem menuitem;
ToolStripMenuItem subitem;
//
menuitem = new ToolStripMenuItem(strings.SetPassword + "...");
menuitem.Name = "setPasswordMenuItem";
menuitem.Click += ContextMenu_Click;
this.ContextMenuStrip.Items.Add(menuitem);
this.ContextMenuStrip.Items.Add(new ToolStripSeparator());
//
menuitem = new ToolStripMenuItem(strings.ShowCode);
menuitem.Name = "showCodeMenuItem";
menuitem.Click += ContextMenu_Click;
this.ContextMenuStrip.Items.Add(menuitem);
//
menuitem = new ToolStripMenuItem(strings.CopyCode);
menuitem.Name = "copyCodeMenuItem";
menuitem.Click += ContextMenu_Click;
this.ContextMenuStrip.Items.Add(menuitem);
//
this.ContextMenuStrip.Items.Add(new ToolStripSeparator());
//
menuitem = new ToolStripMenuItem(strings.ShowSerialAndRestoreCode + "...");
menuitem.Name = "showRestoreCodeMenuItem";
menuitem.Click += ContextMenu_Click;
this.ContextMenuStrip.Items.Add(menuitem);
//
menuitem = new ToolStripMenuItem(strings.ShowSecretKey + "...");
menuitem.Name = "showGoogleSecretMenuItem";
menuitem.Click += ContextMenu_Click;
this.ContextMenuStrip.Items.Add(menuitem);
//
menuitem = new ToolStripMenuItem(strings.ShowSerialKeyAndDeviceId + "...");
menuitem.Name = "showTrionSecretMenuItem";
menuitem.Click += ContextMenu_Click;
this.ContextMenuStrip.Items.Add(menuitem);
//
menuitem = new ToolStripMenuItem(strings.ShowRevocation + "...");
menuitem.Name = "showSteamSecretMenuItem";
menuitem.Click += ContextMenu_Click;
this.ContextMenuStrip.Items.Add(menuitem);
//
this.ContextMenuStrip.Items.Add(new ToolStripSeparator { Name = "steamSeperator" });
//
menuitem = new ToolStripMenuItem(strings.ConfirmTrades + "...");
menuitem.Name = "showSteamTradesMenuItem";
menuitem.Click += ContextMenu_Click;
this.ContextMenuStrip.Items.Add(menuitem);
//
this.ContextMenuStrip.Items.Add(new ToolStripSeparator());
//
menuitem = new ToolStripMenuItem(strings.Delete);
menuitem.Name = "deleteMenuItem";
menuitem.Click += ContextMenu_Click;
this.ContextMenuStrip.Items.Add(menuitem);
//
menuitem = new ToolStripMenuItem(strings.Rename);
menuitem.Name = "renameMenuItem";
menuitem.Click += ContextMenu_Click;
this.ContextMenuStrip.Items.Add(menuitem);
//
this.ContextMenuStrip.Items.Add(new ToolStripSeparator());
//
menuitem = new ToolStripMenuItem(strings.AutoRefresh);
menuitem.Name = "autoRefreshMenuItem";
menuitem.Click += ContextMenu_Click;
this.ContextMenuStrip.Items.Add(menuitem);
//
menuitem = new ToolStripMenuItem(strings.CopyOnNewCode);
menuitem.Name = "copyOnCodeMenuItem";
menuitem.Click += ContextMenu_Click;
this.ContextMenuStrip.Items.Add(menuitem);
//
menuitem = new ToolStripMenuItem(strings.Icon);
menuitem.Name = "iconMenuItem";
subitem = new ToolStripMenuItem();
subitem.Text = strings.IconAuto;
subitem.Name = "iconMenuItem_default";
subitem.Tag = string.Empty;
subitem.Click += ContextMenu_Click;
menuitem.DropDownItems.Add(subitem);
menuitem.DropDownItems.Add("-");
this.ContextMenuStrip.Items.Add(menuitem);
int iconindex = 1;
var parentItem = menuitem;
foreach (Tuple<string,string> entry in WinAuthMain.AUTHENTICATOR_ICONS)
{
string icon = entry.Item1;
string iconfile = entry.Item2;
if (iconfile.Length == 0)
{
parentItem.DropDownItems.Add(new ToolStripSeparator());
}
else if (icon.StartsWith("+") == true)
{
if (parentItem.Tag is ToolStripMenuItem)
{
parentItem = parentItem.Tag as ToolStripMenuItem;
}
subitem = new ToolStripMenuItem();
subitem.Text = icon.Substring(1);
//subitem.Name = "iconMenuItem_" + iconindex++;
subitem.Tag = parentItem;
subitem.Image = new Bitmap(Assembly.GetExecutingAssembly().GetManifestResourceStream("WinAuth.Resources." + iconfile));
subitem.ImageAlign = ContentAlignment.MiddleLeft;
subitem.ImageScaling = ToolStripItemImageScaling.SizeToFit;
//subitem.Click += ContextMenu_Click;
parentItem.DropDownItems.Add(subitem);
parentItem = subitem;
}
else
{
subitem = new ToolStripMenuItem();
subitem.Text = icon;
subitem.Name = "iconMenuItem_" + iconindex++;
subitem.Tag = iconfile;
subitem.Image = new Bitmap(Assembly.GetExecutingAssembly().GetManifestResourceStream("WinAuth.Resources." + iconfile));
subitem.ImageAlign = ContentAlignment.MiddleLeft;
subitem.ImageScaling = ToolStripItemImageScaling.SizeToFit;
subitem.Click += ContextMenu_Click;
parentItem.DropDownItems.Add(subitem);
}
}
menuitem.DropDownItems.Add("-");
subitem = new ToolStripMenuItem();
subitem.Text = strings.Other + "...";
subitem.Name = "iconMenuItem_0";
subitem.Tag = "OTHER";
subitem.Click += ContextMenu_Click;
menuitem.DropDownItems.Add(subitem);
this.ContextMenuStrip.Items.Add(menuitem);
//
this.ContextMenuStrip.Items.Add(new ToolStripSeparator());
//
menuitem = new ToolStripMenuItem(strings.ShortcutKey + "...");
menuitem.Name = "shortcutKeyMenuItem";
menuitem.Click += ContextMenu_Click;
this.ContextMenuStrip.Items.Add(menuitem);
//
ToolStripSeparator sepitem = new ToolStripSeparator();
sepitem.Name = "syncMenuSep";
this.ContextMenuStrip.Items.Add(sepitem);
//
menuitem = new ToolStripMenuItem(strings.SyncTime);
menuitem.Name = "syncMenuItem";
menuitem.Click += ContextMenu_Click;
this.ContextMenuStrip.Items.Add(menuitem);
}
/// <summary>
/// Set the options for the context menu items based on the currnet authenticator and state
/// </summary>
private void SetContextMenuItems()
{
var menu = this.ContextMenuStrip;
var item = this.CurrentItem;
WinAuthAuthenticator auth = null;
if (item == null || (auth = item.Authenticator) == null || auth.AuthenticatorData == null)
{
return;
}
ToolStripLabel labelitem = menu.Items.Cast<ToolStripItem>().Where(i => i.Name == "contextMenuItemName").FirstOrDefault() as ToolStripLabel;
labelitem.Text = item.Authenticator.Name;
if (auth.HotKey != null)
{
labelitem.Text += " (" + auth.HotKey.ToString() + ")";
}
ToolStripItem sepitem;
ToolStripMenuItem menuitem = menu.Items.Cast<ToolStripItem>().Where(i => i.Name == "setPasswordMenuItem").FirstOrDefault() as ToolStripMenuItem;
menuitem.Text = (item.Authenticator.AuthenticatorData.PasswordType == Authenticator.PasswordTypes.Explicit ? strings.ChangeOrRemovePassword + "..." : strings.SetPassword + "...");
menuitem = menu.Items.Cast<ToolStripItem>().Where(i => i.Name == "showCodeMenuItem").FirstOrDefault() as ToolStripMenuItem;
menuitem.Visible = !auth.AutoRefresh;
//
menuitem = menu.Items.Cast<ToolStripItem>().Where(i => i.Name == "showRestoreCodeMenuItem").FirstOrDefault() as ToolStripMenuItem;
menuitem.Visible = (auth.AuthenticatorData is BattleNetAuthenticator);
//
menuitem = menu.Items.Cast<ToolStripItem>().Where(i => i.Name == "showGoogleSecretMenuItem").FirstOrDefault() as ToolStripMenuItem;
menuitem.Visible = (auth.AuthenticatorData is GoogleAuthenticator || auth.AuthenticatorData is HOTPAuthenticator);
//
menuitem = menu.Items.Cast<ToolStripItem>().Where(i => i.Name == "showTrionSecretMenuItem").FirstOrDefault() as ToolStripMenuItem;
menuitem.Visible = (auth.AuthenticatorData is TrionAuthenticator);
//
menuitem = menu.Items.Cast<ToolStripItem>().Where(i => i.Name == "showSteamSecretMenuItem").FirstOrDefault() as ToolStripMenuItem;
menuitem.Visible = (auth.AuthenticatorData is SteamAuthenticator);
menuitem.Enabled = (auth.AuthenticatorData is SteamAuthenticator && string.IsNullOrEmpty(((SteamAuthenticator)auth.AuthenticatorData).SteamData) == false);
//
sepitem = menu.Items.Cast<ToolStripItem>().Where(i => i.Name == "steamSeperator").FirstOrDefault() as ToolStripItem;
sepitem.Visible = (auth.AuthenticatorData is SteamAuthenticator);
//
menuitem = menu.Items.Cast<ToolStripItem>().Where(i => i.Name == "showSteamTradesMenuItem").FirstOrDefault() as ToolStripMenuItem;
menuitem.Visible = (auth.AuthenticatorData is SteamAuthenticator);
menuitem.Enabled = (auth.AuthenticatorData is SteamAuthenticator && string.IsNullOrEmpty(((SteamAuthenticator)auth.AuthenticatorData).SteamData) == false);
//
menuitem = menu.Items.Cast<ToolStripItem>().Where(i => i.Name == "autoRefreshMenuItem").FirstOrDefault() as ToolStripMenuItem;
menuitem.Visible = !(auth.AuthenticatorData is HOTPAuthenticator);
menuitem.CheckState = (auth.AutoRefresh == true ? CheckState.Checked : CheckState.Unchecked);
menuitem.Enabled = (auth.AuthenticatorData.RequiresPassword == false && auth.AuthenticatorData.PasswordType != Authenticator.PasswordTypes.Explicit);
//
menuitem = menu.Items.Cast<ToolStripItem>().Where(i => i.Name == "copyOnCodeMenuItem").FirstOrDefault() as ToolStripMenuItem;
menuitem.CheckState = (auth.CopyOnCode == true ? CheckState.Checked : CheckState.Unchecked);
//
menuitem = menu.Items.Cast<ToolStripItem>().Where(i => i.Name == "iconMenuItem").FirstOrDefault() as ToolStripMenuItem;
ToolStripMenuItem subitem = menuitem.DropDownItems.Cast<ToolStripItem>().Where(i => i.Name == "iconMenuItem_default").FirstOrDefault() as ToolStripMenuItem;
subitem.CheckState = CheckState.Checked;
foreach (ToolStripItem iconitem in menuitem.DropDownItems)
{
if (iconitem is ToolStripMenuItem && iconitem.Tag is string)
{
ToolStripMenuItem iconmenuitem = (ToolStripMenuItem)iconitem;
if (string.IsNullOrEmpty((string)iconmenuitem.Tag) && string.IsNullOrEmpty(auth.Skin) == true)
{
iconmenuitem.CheckState = CheckState.Checked;
}
else if (string.Compare((string)iconmenuitem.Tag, auth.Skin) == 0)
{
iconmenuitem.CheckState = CheckState.Checked;
}
else
{
iconmenuitem.CheckState = CheckState.Unchecked;
}
}
}
//
sepitem = menu.Items.Cast<ToolStripItem>().Where(i => i.Name == "syncMenuSep").FirstOrDefault() as ToolStripItem;
sepitem.Visible = !(auth.AuthenticatorData is HOTPAuthenticator);
menuitem = menu.Items.Cast<ToolStripItem>().Where(i => i.Name == "syncMenuItem").FirstOrDefault() as ToolStripMenuItem;
menuitem.Visible = !(auth.AuthenticatorData is HOTPAuthenticator);
}
/// <summary>
/// Process the context menu item
/// </summary>
/// <param name="menuitem"></param>
private void ProcessMenu(ToolStripItem menuitem)
{
var item = this.CurrentItem;
var auth = item.Authenticator;
// check and perform each menu
if (menuitem.Name == "setPasswordMenuItem")
{
// check if the authentcated is still protected
DialogResult wasprotected = UnprotectAuthenticator(item);
if (wasprotected == DialogResult.Cancel)
{
return;
}
try
{
// show the new password form
SetPasswordForm form = new SetPasswordForm();
if (form.ShowDialog(this.Parent as Form) != DialogResult.OK)
{
return;
}
// set the encrpytion
string password = form.Password;
if (string.IsNullOrEmpty(password) == false)
{
auth.AuthenticatorData.SetEncryption(Authenticator.PasswordTypes.Explicit, password);
// can't have autorefresh on
auth.AutoRefresh = false;
item.UnprotectCount = 0;
item.DisplayUntil = DateTime.MinValue;
item.LastUpdate = DateTime.MinValue;
item.LastCode = null;
}
else
{
auth.AuthenticatorData.SetEncryption(Authenticator.PasswordTypes.None);
}
// make sure authenticator is saved
auth.MarkChanged();
RefreshCurrentItem();
}
finally
{
if (wasprotected == DialogResult.OK)
{
ProtectAuthenticator(item);
}
}
}
else if (menuitem.Name == "showCodeMenuItem")
{
// check if the authentcated is still protected
if (UnprotectAuthenticator(item) == DialogResult.Cancel)
{
return;
}
// reduce unprotect count if already displayed
if (item.DisplayUntil != DateTime.MinValue)
{
ProtectAuthenticator(item);
}
item.LastCode = auth.CurrentCode;
item.LastUpdate = DateTime.Now;
item.DisplayUntil = DateTime.Now.AddSeconds(10);
RefreshCurrentItem();
}
else if (menuitem.Name == "copyCodeMenuItem")
{
// check if the authentcated is still protected
DialogResult wasprotected = UnprotectAuthenticator(item);
if (wasprotected == DialogResult.Cancel)
{
return;
}
try
{
auth.CopyCodeToClipboard(this.Parent as Form, item.LastCode, true);
}
finally
{
if (wasprotected == DialogResult.OK)
{
ProtectAuthenticator(item);
}
}
}
else if (menuitem.Name == "autoRefreshMenuItem")
{
auth.AutoRefresh = !auth.AutoRefresh;
item.LastUpdate = DateTime.Now;
item.DisplayUntil = DateTime.MinValue;
RefreshCurrentItem();
}
else if (menuitem.Name == "shortcutKeyMenuItem")
{
DialogResult wasprotected = UnprotectAuthenticator(item);
if (wasprotected == DialogResult.Cancel)
{
return;
}
try
{
SetShortcutKeyForm form = new SetShortcutKeyForm();
form.Hotkey = auth.HotKey;
if (form.ShowDialog(this.Parent as Form) != DialogResult.OK)
{
return;
}
auth.HotKey = form.Hotkey;
}
finally
{
if (wasprotected == DialogResult.OK)
{
ProtectAuthenticator(item);
}
}
}
else if (menuitem.Name == "copyOnCodeMenuItem")
{
auth.CopyOnCode = !auth.CopyOnCode;
}
else if (menuitem.Name == "showRestoreCodeMenuItem")
{
// check if the authentcated is still protected
DialogResult wasprotected = UnprotectAuthenticator(item);
if (wasprotected == DialogResult.Cancel)
{
return;
}
try
{
if (wasprotected != DialogResult.OK)
{
// confirm current main password
var mainform = this.Parent as WinAuthForm;
if ((mainform.Config.PasswordType & Authenticator.PasswordTypes.Explicit) != 0)
{
bool invalidPassword = false;
while (true)
{
GetPasswordForm checkform = new GetPasswordForm();
checkform.InvalidPassword = invalidPassword;
var result = checkform.ShowDialog(this);
if (result == DialogResult.Cancel)
{
return;
}
if (mainform.Config.IsPassword(checkform.Password) == true)
{
break;
}
invalidPassword = true;
}
}
}
// show the serial and restore code for Battle.net authenticator
ShowRestoreCodeForm form = new ShowRestoreCodeForm();
form.CurrentAuthenticator = auth;
form.ShowDialog(this.Parent as Form);
}
finally
{
if (wasprotected == DialogResult.OK)
{
ProtectAuthenticator(item);
}
}
}
else if (menuitem.Name == "showGoogleSecretMenuItem")
{
// check if the authentcated is still protected
DialogResult wasprotected = UnprotectAuthenticator(item);
if (wasprotected == DialogResult.Cancel)
{
return;
}
try
{
if (wasprotected != DialogResult.OK)
{
// confirm current main password
var mainform = this.Parent as WinAuthForm;
if ((mainform.Config.PasswordType & Authenticator.PasswordTypes.Explicit) != 0)
{
bool invalidPassword = false;
while (true)
{
GetPasswordForm checkform = new GetPasswordForm();
checkform.InvalidPassword = invalidPassword;
var result = checkform.ShowDialog(this);
if (result == DialogResult.Cancel)
{
return;
}
if (mainform.Config.IsPassword(checkform.Password) == true)
{
break;
}
invalidPassword = true;
}
}
}
// show the secret key for Google authenticator
ShowSecretKeyForm form = new ShowSecretKeyForm();
form.CurrentAuthenticator = auth;
form.ShowDialog(this.Parent as Form);
}
finally
{
if (wasprotected == DialogResult.OK)
{
ProtectAuthenticator(item);
}
}
}
else if (menuitem.Name == "showTrionSecretMenuItem")
{
// check if the authenticator is still protected
DialogResult wasprotected = UnprotectAuthenticator(item);
if (wasprotected == DialogResult.Cancel)
{
return;
}
try
{
// show the secret key for Trion authenticator
ShowTrionSecretForm form = new ShowTrionSecretForm();
form.CurrentAuthenticator = auth;
form.ShowDialog(this.Parent as Form);
}
finally
{
if (wasprotected == DialogResult.OK)
{
ProtectAuthenticator(item);
}
}
}
else if (menuitem.Name == "showSteamSecretMenuItem")
{
// check if the authenticator is still protected
DialogResult wasprotected = UnprotectAuthenticator(item);
if (wasprotected == DialogResult.Cancel)
{
return;
}
try
{
if (wasprotected != DialogResult.OK)
{
// confirm current main password
var mainform = this.Parent as WinAuthForm;
if ((mainform.Config.PasswordType & Authenticator.PasswordTypes.Explicit) != 0)
{
bool invalidPassword = false;
while (true)
{
GetPasswordForm checkform = new GetPasswordForm();
checkform.InvalidPassword = invalidPassword;
var result = checkform.ShowDialog(this);
if (result == DialogResult.Cancel)
{
return;
}
if (mainform.Config.IsPassword(checkform.Password) == true)
{
break;
}
invalidPassword = true;
}
}
}
// show the secret key for Google authenticator
ShowSteamSecretForm form = new ShowSteamSecretForm();
form.CurrentAuthenticator = auth;
form.ShowDialog(this.Parent as Form);
}
finally
{
if (wasprotected == DialogResult.OK)
{
ProtectAuthenticator(item);
}
}
}
else if (menuitem.Name == "showSteamTradesMenuItem")
{
// check if the authenticator is still protected
DialogResult wasprotected = UnprotectAuthenticator(item);
if (wasprotected == DialogResult.Cancel)
{
return;
}
try
{
// show the Steam trades dialog
ShowSteamTradesForm form = new ShowSteamTradesForm();
form.Authenticator = auth;
form.ShowDialog(this.Parent as Form);
}
finally
{
if (wasprotected == DialogResult.OK)
{
ProtectAuthenticator(item);
}
}
}
else if (menuitem.Name == "deleteMenuItem")
{
if (WinAuthForm.ConfirmDialog(this.Parent as Form, strings.DeleteAuthenticatorWarning, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
{
int index = item.Index;
this.Items.Remove(item);
ItemRemoved(this, new AuthenticatorListItemRemovedEventArgs(item));
if (index >= this.Items.Count)
{
index = this.Items.Count - 1;
}
this.CurrentItem = (this.Items.Count != 0 ? this.Items[index] as AuthenticatorListitem : null);
// reset the correct indexes of our items
for (int i = 0; i < this.Items.Count; i++)
{
(this.Items[i] as AuthenticatorListitem).Index = i;
}
}
}
else if (menuitem.Name == "renameMenuItem")
{
int y = (this.ItemHeight * item.Index) - (this.TopIndex * this.ItemHeight) + 8;
RenameTextbox.Location = new Point(64, y);
RenameTextbox.Text = auth.Name;
RenameTextbox.Tag = item;
RenameTextbox.Visible = true;
RenameTextbox.Focus();
}
else if (menuitem.Name == "syncMenuItem")
{
// check if the authentcated is still protected
DialogResult wasprotected = UnprotectAuthenticator(item);
if (wasprotected == DialogResult.Cancel)
{
return;
}
Cursor cursor = Cursor.Current;
try {
Cursor.Current = Cursors.WaitCursor;
auth.Sync();
RefreshItem(item);
}
finally
{
Cursor.Current = cursor;
if (wasprotected == DialogResult.OK)
{
ProtectAuthenticator(item);
}
}
}
else if (menuitem.Name.StartsWith("iconMenuItem_") == true)
{
if (menuitem.Tag is string && string.Compare((string)menuitem.Tag, "OTHER") == 0)
{
do
{
// other..choose an image file
OpenFileDialog ofd = new OpenFileDialog();
ofd.AddExtension = true;
ofd.CheckFileExists = true;
ofd.DefaultExt = "png";
ofd.InitialDirectory = Directory.GetCurrentDirectory();
ofd.FileName = string.Empty;
ofd.Filter = "PNG Image Files (*.png)|*.png|GIF Image Files (*.gif)|*.gif|All Files (*.*)|*.*";
ofd.RestoreDirectory = true;
ofd.ShowReadOnly = false;
ofd.Title = strings.LoadIconImage + " (png or gif @ 48x48)";
DialogResult result = ofd.ShowDialog(this);
if (result != System.Windows.Forms.DialogResult.OK)
{
return;
}
try
{
// get the image and create an icon if not already the right size
using (Bitmap iconimage = (Bitmap)Image.FromFile(ofd.FileName))
{
if (iconimage.Width != ICON_WIDTH || iconimage.Height != ICON_HEIGHT)
{
using (Bitmap scaled = new Bitmap(ICON_WIDTH, ICON_HEIGHT))
{
using (Graphics g = Graphics.FromImage(scaled))
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.DrawImage(iconimage, new Rectangle(0, 0, ICON_WIDTH, ICON_HEIGHT));
}
auth.Icon = scaled;
}
}
else
{
auth.Icon = iconimage;
}
RefreshCurrentItem();
}
}
catch (Exception ex)
{
if (MessageBox.Show(this.Parent as Form,
string.Format(strings.ErrorLoadingIconFile, ex.Message),
WinAuthMain.APPLICATION_NAME,
MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
{
continue;
}
}
break;
} while (true);
}
else
{
auth.Skin = (((string)menuitem.Tag).Length != 0 ? (string)menuitem.Tag : null);
RefreshCurrentItem();
}
}
}
/// <summary>
/// Get the current code for an item in the list, unprotecting and reprotecting the authenticator if necessary
/// </summary>
/// <param name="item">List item to get code</param>
/// <returns>code or null if failed (i.e. bad password)</returns>
public string GetItemCode(AuthenticatorListitem item, Screen screen = null)
{
WinAuthAuthenticator auth = item.Authenticator;
// check if the authentcated is still protected
DialogResult wasprotected = UnprotectAuthenticator(item, screen);
if (wasprotected == DialogResult.Cancel)
{
return null;
}
try {
return auth.CurrentCode;
}
finally
{
if (wasprotected == DialogResult.OK)
{
ProtectAuthenticator(item);
}
}
}
/// <summary>
/// Refresh the current item by invalidating it
/// </summary>
private void RefreshCurrentItem()
{
RefreshItem(this.CurrentItem);
}
/// <summary>
/// Refresh the item by invalidating it
/// </summary>
private void RefreshItem(AuthenticatorListitem item)
{
bool hasvscroll = (this.Height < (this.Items.Count * this.ItemHeight));
int y = (this.ItemHeight * item.Index) - (this.ItemHeight * this.TopIndex);
Rectangle rect = new Rectangle(0, y, this.Width, this.Height);
this.Invalidate(rect, false);
}
/// <summary>
/// Convert a Bitmap into grayscale
/// http://stackoverflow.com/questions/4669317/how-to-convert-a-bitmap-image-to-black-and-white-in-c
/// </summary>
/// <param name="bmp">Bitmap to convert</param>
/// <returns>Original bitmap but grayscale</returns>
private static Bitmap GrayScale(Bitmap bmp)
{
int rgb;
Color c;
for (int y = 0; y < bmp.Height; y++)
{
for (int x = 0; x < bmp.Width; x++)
{
c = bmp.GetPixel(x, y);
rgb = (int)((c.R * 0.3) + (c.G * 0.59) + (c.B * 0.11));
bmp.SetPixel(x, y, Color.FromArgb(rgb, rgb, rgb));
}
}
return bmp;
}
/// <summary>
/// Lighten or darken a bitmap
/// </summary>
/// <param name="bmp">Bitmap</param>
/// <param name="amount">amount to change 0-255</param>
/// <returns>Original bitmap but darkened</returns>
private static Bitmap Lighten(Bitmap bmp, int amount)
{
Color c;
int r, g, b;
for (int y = 0; y < bmp.Height; y++)
{
for (int x = 0; x < bmp.Width; x++)
{
c = bmp.GetPixel(x, y);
r = Math.Max(Math.Min(c.R + amount, 255), 0);
g = Math.Max(Math.Min(c.G + amount, 255), 0);
b = Math.Max(Math.Min(c.B + amount, 255), 0);
bmp.SetPixel(x, y, Color.FromArgb(r, g, b));
}
}
return bmp;
}
#endregion
#region Owner Draw
/// <summary>
/// Calculate the maximum available label with based on the currnet control size
/// </summary>
/// <param name="totalWidth">control size</param>
/// <returns>maximum possible width for label</returns>
protected int GetMaxAvailableLabelWidth(int totalWidth)
{
return totalWidth - MARGIN_LEFT - ICON_WIDTH - ICON_MARGIN_RIGHT - PIE_WIDTH - MARGIN_RIGHT;
}
/// <summary>
/// Calculate the maximum label width based on the currnet names
/// </summary>
/// <param name="totalWidth">control size</param>
/// <returns>maximum possible width for label</returns>
public int GetMaxItemWidth()
{
var items = this.Items.Cast<AuthenticatorListitem>();
if (items.Where(i => i.AutoWidth == 0).Count() != 0)
{
using (Graphics g = this.CreateGraphics())
{
using (var font = new Font(this.Font.FontFamily, FONT_SIZE, FontStyle.Regular))
{
foreach (AuthenticatorListitem item in items.Where(i => i.AutoWidth == 0))
{
WinAuthAuthenticator auth = item.Authenticator;
SizeF labelsize = g.MeasureString(auth.Name, font);
item.AutoWidth = MARGIN_LEFT + ICON_WIDTH + ICON_MARGIN_RIGHT + (int)Math.Ceiling(labelsize.Width) + PIE_WIDTH + MARGIN_RIGHT;
}
}
}
}
int maxWidth = this.Items.Cast<AuthenticatorListitem>().Max(i => i.AutoWidth);
return maxWidth;
}
/// <summary>
/// Hook into the default WndProc to make sure we get our redraw messages
/// </summary>
/// <param name="m"></param>
protected override void DefWndProc(ref Message m)
{
if (ReadOnly == false || ((m.Msg <= 0x0200 || m.Msg >= 0x020E)
&& (m.Msg <= 0x0100 || m.Msg >= 0x0109)
&& m.Msg != 0x2111
&& m.Msg != 0x87))
{
base.DefWndProc(ref m);
}
}
/// <summary>
/// Event called when an item requires drawing
/// </summary>
/// <param name="e"></param>
/// <param name="cliprect"></param>
protected void OnDrawItem(DrawItemEventArgs e, Rectangle cliprect)
{
// no need to draw nothing
if (this.Items.Count == 0 || e.Index < 0)
{
return;
}
AuthenticatorListitem item = this.Items[e.Index] as AuthenticatorListitem;
WinAuthAuthenticator auth = item.Authenticator;
// if the item is being dragged, we draw a blank placeholder
if (item.Dragging == true)
{
if (cliprect.IntersectsWith(e.Bounds) == true)
{
using (var brush = new SolidBrush(SystemColors.ControlLightLight))
{
using (Pen pen = new Pen(SystemColors.Control))
{
e.Graphics.DrawRectangle(pen, e.Bounds);
e.Graphics.FillRectangle(brush, e.Bounds);
}
}
}
return;
}
// draw the requested item
using (var brush = new SolidBrush(e.ForeColor))
{
bool showCode = (auth.AutoRefresh == true || item.DisplayUntil > DateTime.Now);
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
Rectangle rect = new Rectangle(e.Bounds.X + MARGIN_LEFT, e.Bounds.Y + MARGIN_TOP, ICON_WIDTH, ICON_HEIGHT);
if (cliprect.IntersectsWith(rect) == true)
{
using (var icon = auth.Icon)
{
if (icon != null)
{
e.Graphics.DrawImage(icon, new PointF(e.Bounds.X + MARGIN_LEFT, e.Bounds.Y + MARGIN_TOP));
}
}
}
using (var font = new Font(e.Font.FontFamily, FONT_SIZE, FontStyle.Regular))
{
string label = auth.Name;
SizeF labelsize = e.Graphics.MeasureString(label.ToString(), font);
int labelMaxWidth = GetMaxAvailableLabelWidth(e.Bounds.Width);
if (labelsize.Width > labelMaxWidth)
{
StringBuilder newlabel = new StringBuilder(label + "...");
while ((labelsize = e.Graphics.MeasureString(newlabel.ToString(), font)).Width > labelMaxWidth)
{
newlabel.Remove(newlabel.Length - 4, 1);
}
label = newlabel.ToString();
}
rect = new Rectangle(e.Bounds.X + 64, e.Bounds.Y + MARGIN_TOP, (int)labelsize.Height, (int)labelsize.Width);
if (cliprect.IntersectsWith(rect) == true)
{
e.Graphics.DrawString(label, font, brush, new RectangleF(e.Bounds.X + MARGIN_LEFT + ICON_WIDTH + ICON_MARGIN_RIGHT, e.Bounds.Y + MARGIN_TOP, labelMaxWidth, labelsize.Height));
}
string code;
if (showCode == true)
{
try
{
// we we aren't autorefresh we just keep the same code up for the 10 seconds so it doesn't change even crossing the 30s boundary
if (auth.AutoRefresh == false)
{
if (item.LastCode == null)
{
code = auth.CurrentCode;
}
else
{
code = item.LastCode;
}
}
else
{
code = auth.CurrentCode;
if (code != item.LastCode && auth.CopyOnCode == true)
{
// code has changed - copy to clipboard
auth.CopyCodeToClipboard(this.Parent as Form, code);
}
}
item.LastCode = code;
if (code != null && code.Length > 5)
{
code = code.Insert(code.Length / 2, " ");
}
}
catch (EncryptedSecretDataException )
{
code = "- - - - - -";
}
}
else
{
code = "- - - - - -";
}
SizeF codesize = e.Graphics.MeasureString(code, e.Font);
rect = new Rectangle(e.Bounds.X + MARGIN_LEFT + ICON_WIDTH + ICON_MARGIN_RIGHT, e.Bounds.Y + MARGIN_TOP + (int)labelsize.Height + LABEL_MARGIN_BOTTOM, (int)codesize.Width, (int)codesize.Height);
if (cliprect.IntersectsWith(rect) == true)
{
e.Graphics.DrawString(code, e.Font, brush, new PointF(e.Bounds.X + MARGIN_LEFT + ICON_WIDTH + ICON_MARGIN_RIGHT, e.Bounds.Y + MARGIN_TOP + labelsize.Height + LABEL_MARGIN_BOTTOM));
}
}
// draw the refresh image or pie
rect = new Rectangle(e.Bounds.X + e.Bounds.Width - (MARGIN_RIGHT + ICON_WIDTH), e.Bounds.Y + MARGIN_TOP, ICON_WIDTH, ICON_HEIGHT);
if (cliprect.IntersectsWith(rect) == true)
{
if (auth.AutoRefresh == true)
{
using (var piebrush = new SolidBrush(SystemColors.ActiveCaption))
{
using (var piepen = new Pen(SystemColors.ActiveCaption))
{
//int y = (this.TopIndex * this.ItemHeight) + e.Bounds.y
//int tillUpdate = ((int)((auth.AuthenticatorData.ServerTime % 30000) / 1000L) + 1) * 12;
int tillUpdate = (int)Math.Round((decimal)((auth.AuthenticatorData.ServerTime % ((long)auth.AuthenticatorData.Period * 1000L)) / 1000L) * (360M / (decimal)auth.AuthenticatorData.Period));
e.Graphics.DrawPie(piepen, e.Bounds.X + e.Bounds.Width - (MARGIN_RIGHT + ICON_WIDTH), e.Bounds.Y + MARGIN_TOP + PIE_MARGIN, PIE_WIDTH, PIE_HEIGHT, PIE_STARTANGLE, PIE_SWEEPANGLE);
e.Graphics.FillPie(piebrush, e.Bounds.X + e.Bounds.Width - (MARGIN_RIGHT + ICON_WIDTH), e.Bounds.Y + MARGIN_TOP + PIE_MARGIN, PIE_WIDTH, PIE_HEIGHT, PIE_STARTANGLE, tillUpdate);
}
}
}
else
{
if (showCode == true)
{
using (var piebrush = new SolidBrush(SystemColors.ActiveCaption))
{
using (var piepen = new Pen(SystemColors.ActiveCaption))
{
int tillUpdate = (int)((item.DisplayUntil.Subtract(DateTime.Now).TotalSeconds * (double)360) / item.DisplayUntil.Subtract(item.LastUpdate).TotalSeconds);
e.Graphics.DrawPie(piepen, e.Bounds.X + e.Bounds.Width - (MARGIN_RIGHT + ICON_WIDTH), e.Bounds.Y + MARGIN_TOP + PIE_MARGIN, PIE_WIDTH, PIE_HEIGHT, PIE_STARTANGLE, PIE_SWEEPANGLE);
e.Graphics.FillPie(piebrush, e.Bounds.X + e.Bounds.Width - (MARGIN_RIGHT + ICON_WIDTH), e.Bounds.Y + MARGIN_TOP + PIE_MARGIN, PIE_WIDTH, PIE_HEIGHT, PIE_STARTANGLE, tillUpdate);
}
}
}
else if (auth.AuthenticatorData != null && auth.AuthenticatorData.RequiresPassword == true)
{
e.Graphics.DrawImage(WinAuth.Properties.Resources.RefreshIconWithLock, rect);
}
else
{
e.Graphics.DrawImage(WinAuth.Properties.Resources.RefreshIcon, rect);
}
}
}
// draw the separating line
rect = new Rectangle(e.Bounds.X, e.Bounds.Y + this.ItemHeight - 1, 1, 1);
if (cliprect.IntersectsWith(rect) == true)
{
using (Pen pen = new Pen(SystemColors.Control))
{
e.Graphics.DrawLine(pen, e.Bounds.X, e.Bounds.Y + this.ItemHeight - 1, e.Bounds.X + e.Bounds.Width, e.Bounds.Y + this.ItemHeight - 1);
}
}
}
}
/// <summary>
/// Handle the paint event and work out if item needs redrawing
/// </summary>
/// <param name="e"></param>
protected override void OnPaint(PaintEventArgs e)
{
using (var brush = new SolidBrush(this.BackColor))
{
Region region = new Region(e.ClipRectangle);
e.Graphics.FillRegion(brush, region);
if (this.Items.Count > 0)
{
for (int i = 0; i < this.Items.Count; ++i)
{
Rectangle irect = this.GetItemRectangle(i);
if (e.ClipRectangle.IntersectsWith(irect))
{
if ((this.SelectionMode == SelectionMode.One && this.SelectedIndex == i)
|| (this.SelectionMode == SelectionMode.MultiSimple && this.SelectedIndices.Contains(i))
|| (this.SelectionMode == SelectionMode.MultiExtended && this.SelectedIndices.Contains(i)))
{
DrawItemEventArgs diea = new DrawItemEventArgs(e.Graphics, this.Font,
irect, i,
DrawItemState.Selected, this.ForeColor,
this.BackColor);
OnDrawItem(diea, e.ClipRectangle);
base.OnDrawItem(diea);
}
else
{
DrawItemEventArgs diea = new DrawItemEventArgs(e.Graphics, this.Font,
irect, i,
DrawItemState.Default, this.ForeColor,
this.BackColor);
OnDrawItem(diea, e.ClipRectangle);
base.OnDrawItem(diea);
}
region.Complement(irect);
}
}
}
}
base.OnPaint(e);
}
#endregion
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/YongboZhu/winauth.git
git@gitee.com:YongboZhu/winauth.git
YongboZhu
winauth
winauth
master

搜索帮助