diff --git a/EntryTemplateManager.ChildViewer.cs b/EntryTemplateManager.ChildViewer.cs index 608ca04..e058768 100644 --- a/EntryTemplateManager.ChildViewer.cs +++ b/EntryTemplateManager.ChildViewer.cs @@ -12,12 +12,14 @@ using KeePassLib; using KeePassLib.Cryptography.PasswordGenerator; using KeePassLib.Security; +using KeePassLib.Utility; + namespace KPEntryTemplates { partial class EntryTemplateManager { Dictionary et_to_label; Dictionary et_to_control; Dictionary et_to_control2; - Dictionary et_to_secure_edit; + Dictionary et_to_secure_edit; private Button client_remove_button; private Button m_btnGenPw; @@ -37,11 +39,10 @@ private void add_child_items_to_tab(TabPage page) { } page.Controls.Add(client_remove_button); - form.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - form.AutoScaleMode = AutoScaleMode.Font; + } - private SecureEdit current_password_field; - private SecureEdit current_password_confirm_field; + private SecureTextBoxEx current_password_field; + private SecureTextBoxEx current_password_confirm_field; private TextBox current_password_confirm_field_txt; private readonly string DeriveFromPrevious = "(" + KPRes.GenPwBasedOnPrevious + ")"; private void OnPwGenClick(object sender, EventArgs e) { @@ -60,7 +61,7 @@ private void OnPwGenClick(object sender, EventArgs e) { } private void OnPwGenOpen(object sender, EventArgs e) { PwGeneratorForm pgf = new PwGeneratorForm(); - ProtectedString ps = new ProtectedString(true, current_password_field.ToUtf8()); + ProtectedString ps = current_password_field.TextEx; bool bAtLeastOneChar = (ps.Length > 0); PwProfile opt = PwProfile.DeriveFromPassword(ps); @@ -71,17 +72,15 @@ private void OnPwGenOpen(object sender, EventArgs e) { PwGenerator.Generate(out psNew, pgf.SelectedProfile, pbEntropy, Program.PwGeneratorPool); - current_password_field.SetPassword(psNew.ReadUtf8()); - current_password_confirm_field.SetPassword(psNew.ReadUtf8()); + current_password_confirm_field.TextEx = current_password_field.TextEx = psNew; } } private void OnProfilesDynamicMenuClick(object sender, DynamicMenuEventArgs e) { PwProfile pwp = null; if (e.ItemName == DeriveFromPrevious) { - pwp = PwProfile.DeriveFromPassword(new ProtectedString(true, current_password_field.ToUtf8())); - } - else { + pwp = PwProfile.DeriveFromPassword(current_password_field.TextEx); + } else { foreach (PwProfile pwgo in Program.Config.PasswordGenerator.UserProfiles) { if (pwgo.Name == e.ItemName) { pwp = pwgo; @@ -94,11 +93,8 @@ private void OnProfilesDynamicMenuClick(object sender, DynamicMenuEventArgs e) { ProtectedString psNew; PwGenerator.Generate(out psNew, pwp, null, m_host.PwGeneratorPool); - current_password_field.SetPassword(psNew.ReadUtf8()); - current_password_confirm_field.SetPassword(psNew.ReadUtf8()); - - } - else { Debug.Assert(false); } + current_password_confirm_field.TextEx = current_password_field.TextEx = psNew; + } else { Debug.Assert(false); } } private void init_pwgen_button() { m_ctxPwGenOpen = new ToolStripMenuItem(); @@ -108,9 +104,10 @@ private void init_pwgen_button() { m_ctxPwGenProfiles.Size = new Size(208, 22); m_ctxPwGenProfiles.Text = "Generate Using Profile"; m_btnGenPw = new Button(); - m_btnGenPw.Image = Resources.Resources.B15x13_KGPG_Gen; + m_btnGenPw.Image = DpiUtil.ScaleImage(Resources.Resources.B15x13_KGPG_Gen, false); m_btnGenPw.Location = new Point(423, 90); - m_btnGenPw.Size = new Size(32, 23); + + m_btnGenPw.Size = new Size(DpiUtil.ScaleIntX(32), DpiUtil.ScaleIntY(23)); m_btnGenPw.UseVisualStyleBackColor = true; m_btnGenPw.Click += OnPwGenClick; m_ctxPwGen = new ContextMenuStrip(); @@ -161,29 +158,96 @@ public static Dictionary get_template_title_to_field_dict(IPlugi } return ret; } - - //private int ScaleX(int i) { - // return DpiUtil.ScaleIntX(i); - //} - //private int ScaleY(int i) { - // return DpiUtil.ScaleIntY(i); - //} - + public static void UpdateControlSize(Control control) { + var template = control.Tag as EntryTemplate; + if (template == null) { + return; + } + SetControlSizing(template, control); + } + private static void SetControlSizing(EntryTemplate template, Control control) { + int? width = CONTROL_WIDTH; + int? left = LEFT_CONTROL_OFFSET; + int? top=null; + int? height=null; + if (template == null) { + if (control is Label) { + width = LABEL_WIDTH; + left = 0; + } + } else { + switch (template.type) { + case "DataGridView": + left = null; + + width = PAGE_WIDTH; + height = PAGE_HEIGHT - BUTTON_HEIGHT - DpiUtil.ScaleIntY(10); + if (control is Button) { + top = height + DpiUtil.ScaleIntY(5); + height = BUTTON_HEIGHT; + width = PAGE_WIDTH - DpiUtil.ScaleIntX(140) - DpiUtil.ScaleIntX(45); + } + break; + case "Divider": + width = CONTROL_WIDTH + LABEL_WIDTH; + break; + case "Checkbox": + width = null; + break; + case "Inline URL": + width = CONTROL_WIDTH - 30; + if (control is LinkLabel) { + left = left + width + DpiUtil.ScaleIntX(10); + width = null; + } + break; + case "Protected Inline": + if (control is CheckBox || control is Button) { + left = left + width + DpiUtil.ScaleIntX(10); + width = null; + } + break; + } + } + if (left != null) + control.Left = (int)left; + if (width != null) + control.Width = (int)width; + if (top != null) + control.Top = (int)top; + if (height != null) + control.Height = (int)height; + } + public static void SetBaseSizes(TabPage page) { + LABEL_WIDTH = DpiUtil.ScaleIntX(130); + LEFT_CONTROL_OFFSET = LABEL_WIDTH + DpiUtil.ScaleIntX(5); + CONTROL_WIDTH = page.ClientSize.Width - LABEL_WIDTH - DpiUtil.ScaleIntX(70);//minus some so scrolling doesnt cause an issue + PAGE_WIDTH = page.ClientSize.Width; + PAGE_HEIGHT = page.ClientSize.Height; + BUTTON_HEIGHT = DpiUtil.ScaleIntY(20); + } + private static int BUTTON_HEIGHT; + private static int CONTROL_WIDTH; + private static int LEFT_CONTROL_OFFSET; + private static int LABEL_WIDTH; + private static int PAGE_WIDTH; + private static int PAGE_HEIGHT; private bool InitializeChildView(TabPage page, String uuid) { if (et_to_label != null) { add_child_items_to_tab(page); return true; } - + SetBaseSizes(page); init_pwgen_button(); + et_to_label = new Dictionary(); et_to_control = new Dictionary(); - et_to_secure_edit = new Dictionary(); + et_to_secure_edit = new Dictionary(); et_to_control2 = new Dictionary(); - SecureEdit entry_pass = null; - SecureEdit entry_pass_confirm = null; + SecureTextBoxEx entry_pass = null; + SecureTextBoxEx entry_pass_confirm = null; - int control_offset_y = 10; + int control_offset_y = DpiUtil.ScaleIntY(10); PwUuid par_uuid = new PwUuid(KeePassLib.Utility.MemUtil.HexStringToByteArray(uuid)); PwEntry par_template = m_host.Database.RootGroup.FindEntry(par_uuid, true); if (par_template == null) @@ -191,18 +255,15 @@ private bool InitializeChildView(TabPage page, String uuid) { if (par_template.Strings.Get("_etm_template") == null) return false; List cur = parse_entry(par_template.Strings); - const int LABEL_WIDTH = 130; - const int LEFT_CONTROL_OFFSET = LABEL_WIDTH + 5; - int CONTROL_WIDTH = page.ClientSize.Width - LABEL_WIDTH - 55; + + foreach (EntryTemplate t in cur) { Label label = new Label(); label.Text = t.title + ":"; //label.AutoSize = false; label.Top = control_offset_y; - label.Left = 0; label.AutoSize = false; - label.Width = LABEL_WIDTH; - + SetControlSizing(null, label); label.AutoEllipsis = true; label.TextAlign = ContentAlignment.MiddleRight; FontUtil.AssignDefaultBold(label); @@ -211,34 +272,25 @@ private bool InitializeChildView(TabPage page, String uuid) { if (t.type == "Divider") { label.Font = new Font(label.Font.FontFamily, label.Font.Size * 1.1f, FontStyle.Bold | FontStyle.Underline); label.TextAlign = ContentAlignment.BottomLeft; - label.Width = CONTROL_WIDTH + LABEL_WIDTH; label.Text = t.title;//remove : et_to_control[t] = null; - } - else if (t.type == "Checkbox") { + } else if (t.type == "Checkbox") { CheckBox checkbox = new CheckBox(); checkbox.Top = control_offset_y; - checkbox.Left = LEFT_CONTROL_OFFSET; et_to_control[t] = checkbox; - } - else if (t.type == "Listbox"){ + } else if (t.type == "Listbox") { ComboBox combobox = new ComboBox(); combobox.Top = control_offset_y; - combobox.Left = LEFT_CONTROL_OFFSET; - combobox.Width = CONTROL_WIDTH; et_to_control[t] = combobox; - if (!String.IsNullOrEmpty(t.options)){ - String[] opts = t.options.Split(new[]{','}, StringSplitOptions.RemoveEmptyEntries); + if (!String.IsNullOrEmpty(t.options)) { + String[] opts = t.options.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (String opt in opts) combobox.Items.Add(opt.Trim()); } - } - else if (t.type == "Date" || t.type == "Time" || t.type == "Date Time") { + } else if (t.type == "Date" || t.type == "Time" || t.type == "Date Time") { DateTimePicker picker = new DateTimePicker(); picker.Top = control_offset_y; - picker.Left = LEFT_CONTROL_OFFSET; picker.CustomFormat = ""; - picker.Width = CONTROL_WIDTH; picker.Format = DateTimePickerFormat.Custom; if (t.type == "Date" || t.type == "Date Time") picker.CustomFormat = System.Globalization.DateTimeFormatInfo.CurrentInfo.ShortDatePattern; @@ -249,84 +301,95 @@ private bool InitializeChildView(TabPage page, String uuid) { if (t.fieldName == "@exp_date") picker.ShowCheckBox = true; et_to_control[t] = picker; - } - else if (t.type == "Inline" || t.type == "Protected Inline" || t.type == "Inline URL") { - TextBox box = new TextBox(); + } else if (t.type == "RichTextbox") { + var box = new CustomRichTextBoxEx(); box.Top = control_offset_y; - box.Left = LEFT_CONTROL_OFFSET; - box.Width = t.type == "Inline URL" ? CONTROL_WIDTH-30 : CONTROL_WIDTH; + int lines = LinesFromOption(t.options); + box.Multiline = lines > 1; + box.Height = DpiUtil.ScaleIntY(13) * lines + DpiUtil.ScaleIntY(10); + box.CtrlEnterAccepts = true; + box.ScrollBars = RichTextBoxScrollBars.Both; + control_offset_y += DpiUtil.ScaleIntY(13) * (lines - 1); + UIUtil.PrepareStandardMultilineControl(box, true, lines > 1); + + et_to_control[t] = box; + } else if (t.type == "Inline" || t.type == "Protected Inline" || t.type == "Inline URL") { + var box = new TextBox(); int lines = LinesFromOption(t.options); if (t.type == "Inline URL") lines = 1; + if (t.type == "Protected Inline") + box = new SecureTextBoxEx(); + box.Top = control_offset_y; + if (lines > 1) { box.Multiline = true; box.AcceptsReturn = true; - box.Height = 13 * lines + 10; + box.Height = DpiUtil.ScaleIntY(13) * lines + DpiUtil.ScaleIntY(10); box.ScrollBars = ScrollBars.Both; - control_offset_y += 13 * (lines-1); + control_offset_y += DpiUtil.ScaleIntY(13) * (lines - 1); } et_to_control[t] = box; if (t.type == "Protected Inline") { - SecureEdit sedit = new SecureEdit(); - sedit.Attach(box, null, true); - et_to_secure_edit[t] = sedit; + et_to_secure_edit[t] = box as SecureTextBoxEx; if (t.fieldName != "@confirm") { CheckBox chk = new CheckBox(); chk.Appearance = Appearance.Button; - chk.Image = Resources.Resources.B17x05_3BlackDots; - chk.Location = new Point(box.Left + box.Width + 10, control_offset_y); - chk.Size = new Size(32, 23); + chk.Image = DpiUtil.ScaleImage(Resources.Resources.B17x05_3BlackDots, false); + chk.Size = new Size(DpiUtil.ScaleIntX(32), DpiUtil.ScaleIntY(23)); chk.TextAlign = ContentAlignment.MiddleCenter; chk.UseVisualStyleBackColor = true; - chk.Tag = t; + chk.Top = control_offset_y; chk.Checked = true; chk.CheckedChanged += chk_CheckedChanged; et_to_control2[t] = chk; - } - else { + } else { et_to_control2[t] = m_btnGenPw; - et_to_control2[t].Location = new Point(box.Left + box.Width + 10, control_offset_y); - current_password_confirm_field = sedit; + et_to_control2[t].Top = control_offset_y; + current_password_confirm_field = box as SecureTextBoxEx; current_password_confirm_field_txt = box; - entry_pass_confirm = sedit; + entry_pass_confirm = box as SecureTextBoxEx; } if (t.fieldName == PwDefs.PasswordField) { - entry_pass = current_password_field = sedit; + entry_pass = current_password_field = box as SecureTextBoxEx; } - }else if (t.type == "Inline URL") { - var link= new LinkLabel {Text = "Open"}; - link.LinkClicked += (sender, args) => WinUtil.OpenUrl(box.Text??"", form.EntryRef); - link.Location = new Point(box.Left + box.Width + 10, control_offset_y); - link.Width = 50; + } else if (t.type == "Inline URL") { + var link = new LinkLabel { Text = "Open" }; + link.LinkClicked += (sender, args) => WinUtil.OpenUrl(box.Text ?? "", form.EntryRef); + link.Top = control_offset_y; + link.Width = DpiUtil.ScaleIntY(50); et_to_control2[t] = link; } - } - else if (t.type == "Popout" || t.type == "Protected Popout") { + } else if (t.type == "Popout" || t.type == "Protected Popout") { Button btn = new Button(); btn.Text = "View/Edit"; if (t.type == "Protected Popout") btn.Text = "View/Edit Secure"; - btn.Tag = t; - btn.Width = CONTROL_WIDTH; - btn.Left = LEFT_CONTROL_OFFSET; - //btn.Height = 20; + btn.Height = BUTTON_HEIGHT; btn.Top = control_offset_y; + btn.Click += btn_popout_Click; et_to_control[t] = btn; } - - control_offset_y += 30; + control_offset_y += DpiUtil.ScaleIntY(30); + if (et_to_control[t] != null) { //only the divider does not + et_to_control[t].Tag = t; + SetControlSizing(t, et_to_control[t]); + } + if (et_to_control2.ContainsKey(t)) { + et_to_control2[t].Tag = t; + SetControlSizing(t, et_to_control2[t]); + } } client_remove_button = new Button(); client_remove_button.Text = "Remove As Template Child"; - client_remove_button.Width = CONTROL_WIDTH; - client_remove_button.Left = LEFT_CONTROL_OFFSET; + client_remove_button.Height = BUTTON_HEIGHT; + SetControlSizing(null, client_remove_button); //client_remove_button.Height = 20; client_remove_button.Top = control_offset_y; client_remove_button.Click += client_remove_button_Click; - if (entry_pass_confirm != null && entry_pass != null){ - } + add_child_items_to_tab(page); return true; } @@ -356,7 +419,15 @@ void btn_popout_Click(object sender, EventArgs e) { void chk_CheckedChanged(object sender, EventArgs e) { CheckBox chk = (CheckBox)sender; EntryTemplate t = (EntryTemplate)chk.Tag; - et_to_secure_edit[t].EnableProtection(chk.Checked); + var sedit = et_to_secure_edit[t]; + sedit.EnableProtection(chk.Checked); + if (sedit == current_password_field && current_password_confirm_field != null) { + if (chk.Checked) + current_password_confirm_field.TextEx = sedit.TextEx; + current_password_confirm_field.Enabled = chk.Checked; + current_password_confirm_field.EnableProtection(chk.Checked); + + } } private DateTimePicker expires_control; private CheckBox expires_cbx_control; @@ -376,12 +447,12 @@ private void find_override_url_control(Form form) { new_override_url_control = get_control_from_form(form, "m_cmbOverrideUrl") as ImageComboBoxEx; if (new_override_url_control == null)//older keepass - override_url_control = get_control_from_form(form, "m_tbOverrideUrl") as TextBox; + override_url_control = get_control_from_form(form, "m_tbOverrideUrl") as TextBox; } - private int LinesFromOption(String val){ + private int LinesFromOption(String val) { if (String.IsNullOrEmpty(val)) return 1; - int ret=1; + int ret = 1; Int32.TryParse(val, out ret); if (ret < 1 || ret > 100) ret = 1; @@ -403,24 +474,22 @@ private void save_child_vals() { continue; } str = new ProtectedString(false, picker.Value.ToString()); - } - else if (t.type == "Checkbox") { + } else if (t.type == "Checkbox") { CheckBox checkbox = (CheckBox)pair.Value; str = new ProtectedString(false, checkbox.Checked.ToString()); - } - else if (t.type == "Inline" || t.type == "Inline URL") { + } else if (t.type == "Inline" || t.type == "Inline URL") { TextBox box = (TextBox)pair.Value; str = new ProtectedString(false, box.Text == null ? "" : box.Text.Replace("\r", "")); - } - else if (t.type == "Listbox"){ - ComboBox combobox = (ComboBox) pair.Value; + } else if (t.type == "RichTextbox") { + var box = (CustomRichTextBoxEx)pair.Value; + str = new ProtectedString(false, box.Text == null ? "" : box.Text.Replace("\r", "")); + } else if (t.type == "Listbox") { + ComboBox combobox = (ComboBox)pair.Value; str = new ProtectedString(false, combobox.SelectedItem == null ? "" : combobox.SelectedItem.ToString()); - } - else if (t.type == "Protected Inline") { - SecureEdit sedit = et_to_secure_edit[t]; - str = new ProtectedString(true,sedit.ToUtf8()); - } - else + } else if (t.type == "Protected Inline") { + var sedit = et_to_secure_edit[t]; + str = sedit.TextEx; + } else continue; str = str.WithProtection(t.type.StartsWith("Protected")); if (t.fieldName == "@confirm") { @@ -455,13 +524,14 @@ private void init_validation_err() { private bool check_confirm_password_ok() { if (current_password_field == null || current_password_confirm_field == null) return true; - if (current_password_field.ContentsEqualTo(current_password_confirm_field) == false) { + if (!current_password_confirm_field.Enabled) + current_password_confirm_field.TextEx = current_password_field.TextEx; + if (current_password_field.TextEx.Equals(current_password_confirm_field.TextEx, false) == false) { init_validation_err(); current_password_confirm_field_txt.BackColor = KeePass.App.AppDefs.ColorEditError; m_ttValidationError.Show(KPRes.PasswordRepeatFailed, current_password_confirm_field_txt); return false; - } - else if (m_ttValidationError != null) + } else if (m_ttValidationError != null) m_ttValidationError.Hide(current_password_confirm_field_txt); current_password_confirm_field_txt.BackColor = Color.White; @@ -497,31 +567,32 @@ private void init_child_vals() { val = val.Replace("\n", "\r\n"); box.Text = val; - } - else if (t.type == "Protected Inline") { - SecureEdit sedit = et_to_secure_edit[t]; - sedit.SetPassword(str.ReadUtf8()); - } - else if (t.type == "Listbox"){ - ComboBox combobox = (ComboBox) pair.Value; + } else if (t.type == "Protected Inline") { + var sedit = et_to_secure_edit[t]; + sedit.TextEx = str; + } else if (t.type == "RichTextbox") { + var box = (CustomRichTextBoxEx)pair.Value; + String val = str.ReadString(); + val = val.Replace("\r", ""); + val = val.Replace("\n", "\r\n"); + box.Text = val; + } else if (t.type == "Listbox") { + ComboBox combobox = (ComboBox)pair.Value; combobox.SelectedItem = str.ReadString(); - } - else if (t.type == "Checkbox") { + } else if (t.type == "Checkbox") { bool val; CheckBox box = (CheckBox)pair.Value; box.Checked = false; if (Boolean.TryParse(str.ReadString(), out val)) box.Checked = val; - } - else if (t.type == "Date" || t.type == "Time" || t.type == "Date Time") { + } else if (t.type == "Date" || t.type == "Time" || t.type == "Date Time") { DateTimePicker picker = (DateTimePicker)pair.Value; if (t.fieldName == "@exp_date") { find_expires_control(form); Debug.Assert(expires_control != null && expires_cbx_control != null); picker.Value = expires_control.Value; picker.Checked = expires_cbx_control.Checked; - } - else { + } else { DateTime val; if (DateTime.TryParse(str.ReadString(), out val)) picker.Value = val; diff --git a/EntryTemplateManager.TemplateEditor.cs b/EntryTemplateManager.TemplateEditor.cs index bdb602c..4565e66 100644 --- a/EntryTemplateManager.TemplateEditor.cs +++ b/EntryTemplateManager.TemplateEditor.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; +using KeePass.UI; using KeePassLib; namespace KPEntryTemplates { @@ -23,6 +24,7 @@ private void InitializeGridView(TabPage page) { return; } + page.HorizontalScroll.Enabled = false; page.SuspendLayout(); dataGridView = new DataGridView(); colTitle = new DataGridViewTextBoxColumn(); @@ -44,15 +46,18 @@ private void InitializeGridView(TabPage page) { dataGridView.DefaultValuesNeeded += dataGridView_DefaultValuesNeeded; dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; dataGridView.Columns.AddRange(new DataGridViewColumn[] { - colTitle, + colTitle, colField, - colFieldName, - colType, + colFieldName, + colType, colOpt,colOptionValue}); dataGridView.Location = new Point(0, 0); dataGridView.Name = "dataGridView"; - dataGridView.Size = new System.Drawing.Size(TAB_WIDTH, TAB_HEIGHT); - dataGridView.TabIndex = 0; + dataGridView.TabIndex = 0; + SetBaseSizes(page); + var template = new EntryTemplate(null, null, "DataGridView", 0, null);//used just for the conrol sizing + SetControlSizing(template, dataGridView); + dataGridView.ScrollBars = ScrollBars.None; dataGridView.DragDrop += dataGridView_DragDrop; dataGridView.DragOver += dataGridView_DragOver; dataGridView.MouseDown += dataGridView_MouseDown; @@ -77,17 +82,17 @@ private void InitializeGridView(TabPage page) { // colField.HeaderText = "Field"; colField.Items.AddRange(new object[] { - "Custom", - "Title", - "Username", - "Password", + "Custom", + "Title", + "Username", + "Password", "Password Confirmation", "URL", "Notes", "Override URL", "Expiry Date"}); colField.Name = "colField"; - colField.Width = 105; + colField.Width = DpiUtil.ScaleIntX(105); colField.DropDownWidth = 180; @@ -98,30 +103,31 @@ private void InitializeGridView(TabPage page) { colFieldName.HeaderText = "Field Name"; colFieldName.Name = "colFieldName"; colFieldName.SortMode = DataGridViewColumnSortMode.NotSortable; - colFieldName.Width = 75; + colFieldName.Width = DpiUtil.ScaleIntX(75); // // colType // colType.HeaderText = "Type"; colType.Name = "colType"; - colType.Width = 100; + colType.Width = DpiUtil.ScaleIntX(100); colType.Items.AddRange(new object[] { - "Inline", + "Inline", "Inline URL", - "Popout", - "Protected Inline", - "Protected Popout", + "Popout", + "Protected Inline", + "Protected Popout", "Date", "Time", "Date Time", "Checkbox", "Divider", - "Listbox" + "Listbox", + "RichTextbox" }); colType.DropDownWidth = 150; - colOpt.HeaderText = "Opt"; + colOpt.HeaderText = "Npt"; colOpt.Name = "colOpt"; - colOpt.Width = 40; + colOpt.Width = DpiUtil.ScaleIntX(40); colOpt.UseColumnTextForButtonValue = true; colOpt.Text = "Opt"; colOpt.ToolTipText = "Option"; @@ -129,25 +135,27 @@ private void InitializeGridView(TabPage page) { colOptionValue.Visible = false; colOptionValue.Name = "colOptionValue"; colOptionValue.Width = 0; - - + + page.Controls.Add(dataGridView); remove_as_template_button = new Button(); remove_as_template_button.Text = "Remove As Template"; - remove_as_template_button.Width = TAB_WIDTH - 140 - 45; - remove_as_template_button.Left = 115; + remove_as_template_button.Height = BUTTON_HEIGHT; + remove_as_template_button.Width = PAGE_WIDTH - DpiUtil.ScaleIntX(140) - DpiUtil.ScaleIntX(45); + remove_as_template_button.Left = DpiUtil.ScaleIntX(85); //remove_as_template_button.Height = 28; remove_as_template_button.UseVisualStyleBackColor = true; - dataGridView.Size = new Size(TAB_WIDTH, TAB_HEIGHT - remove_as_template_button.Height - 10); //have to set its size before setting the buttons size - remove_as_template_button.Top = dataGridView.Height + 5; + + dataGridView.Tag = template; + + remove_as_template_button.Tag = template; remove_as_template_button.Click += remove_as_template_button_Click; + SetControlSizing(template, remove_as_template_button); page.Controls.Add(remove_as_template_button); - form.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - form.AutoScaleMode = AutoScaleMode.Font; page.ResumeLayout(); - + } - private void dataGridView_CellClick(object sender, DataGridViewCellEventArgs e){ + private void dataGridView_CellClick(object sender, DataGridViewCellEventArgs e) { if (e.ColumnIndex != dataGridView.Columns["colOpt"].Index) return; DataGridViewRow row = dataGridView.Rows[e.RowIndex]; @@ -157,6 +165,7 @@ private void dataGridView_CellClick(object sender, DataGridViewCellEventArgs e){ String msg = ""; switch (type) { case "Inline": + case "RichTextbox"://CustomRichTextBoxEx case "Protected Inline": msg = "How many lines to show for the textbox(1-100)?"; break; @@ -164,7 +173,7 @@ private void dataGridView_CellClick(object sender, DataGridViewCellEventArgs e){ msg = "Listbox Items, seperate with each with a comma"; break; } - String ret = OptionsForm.GetOption(msg, (string) row.Cells["colOptionValue"].Value); + String ret = OptionsForm.GetOption(msg, (string)row.Cells["colOptionValue"].Value); if (ret != null) row.Cells["colOptionValue"].Value = ret; } @@ -190,7 +199,7 @@ void dataGridView_EditingControlShowing(object sender, DataGridViewEditingContro else if (cell.OwningColumn.Name == "colType") { box.SelectedIndexChanged += col_type_box_SelectedIndexChanged; } - if (box != null){ + if (box != null) { box.DropDown += box_DropDown; box.SelectedIndexChanged += box_SelectedIndexChanged; } @@ -204,11 +213,12 @@ void box_SelectedIndexChanged(object sender, EventArgs e) { void box_DropDown(object sender, EventArgs e) { ((DataGridViewComboBoxEditingControl)sender).BackColor = Color.White; } - private void SetRowOptionEnabled(DataGridViewRow row, String type){ + private void SetRowOptionEnabled(DataGridViewRow row, String type) { bool opt_enabled = false; switch (type) { case "Inline": case "Protected Inline": + case "RichTextbox": case "Listbox": opt_enabled = true; break; @@ -216,7 +226,7 @@ private void SetRowOptionEnabled(DataGridViewRow row, String type){ (row.Cells["colOpt"] as DataGridViewDisableButtonCell).Enabled = opt_enabled; } - private void col_type_box_SelectedIndexChanged(object sender, EventArgs e){ + private void col_type_box_SelectedIndexChanged(object sender, EventArgs e) { DataGridViewCell cell = dataGridView.CurrentCell; String type = cell.EditedFormattedValue.ToString(); SetRowOptionEnabled(cell.OwningRow, type); @@ -260,7 +270,7 @@ void col_field_box_SelectedIndexChanged(object sender, EventArgs e) { break; case "Notes": fieldName = PwDefs.NotesField; - type = conf.ProtectNotes ? "Protected Inline" : "Inline"; + type = conf.ProtectNotes ? "Protected Inline" : "RichTextbox"; break; default: type = ""; @@ -274,13 +284,13 @@ void col_field_box_SelectedIndexChanged(object sender, EventArgs e) { return; } row.Cells["colType"].ReadOnly = row.Cells["colFieldName"].ReadOnly = read_only; - if (type != ""){ + if (type != "") { row.Cells["colType"].Value = type; SetRowOptionEnabled(row, type); } if (fieldName != "") row.Cells["colFieldName"].Value = fieldName; - + } @@ -293,7 +303,7 @@ void dataGridView_SelectionChanged(object sender, EventArgs e) { to_del = null; } - private void RemoveToDel(){ + private void RemoveToDel() { if (to_del != null) { if (dataGridView.Rows.Contains(to_del)) dataGridView.Rows.Remove(to_del); @@ -369,8 +379,7 @@ void dataGridView_RowValidating(object sender, DataGridViewCellCancelEventArgs e if (res != DialogResult.Retry) { dataGridView.CancelEdit(); to_del = row; - } - else { + } else { e.Cancel = true; row.ErrorText = old_row_err; } @@ -448,8 +457,7 @@ private void init_data_table() { row.Cells["colOptionValue"].Value = t.options; } - } - catch (Exception e) { + } catch (Exception e) { MessageBox.Show(e.Message); } } @@ -481,8 +489,7 @@ private void dataGridView_MouseDown(object sender, MouseEventArgs e) { Size dragSize = SystemInformation.DragSize; dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2), e.Y - (dragSize.Height / 2)), dragSize); - } - else + } else dragBoxFromMouseDown = Rectangle.Empty; } diff --git a/EntryTemplateManager.cs b/EntryTemplateManager.cs index bfb9511..d68ed4c 100644 --- a/EntryTemplateManager.cs +++ b/EntryTemplateManager.cs @@ -10,11 +10,10 @@ using KeePassLib.Utility; using KeePass.UI; using KeePass.Resources; +using System.Threading.Tasks; namespace KPEntryTemplates { partial class EntryTemplateManager { - private const int TAB_WIDTH = 465; - private const int TAB_HEIGHT = 350; private PwEntryForm form; private IPluginHost m_host; @@ -43,7 +42,7 @@ public EntryTemplateManager(IPluginHost host, PwEntryForm form) { form.EntrySaving += form_EntrySaving; our_page.UseVisualStyleBackColor = true; form_tab_control.TabPages.Insert(0, our_page); - if (entry_is_child || entry_is_template) + if (entry_is_child || entry_is_template && !KeePassLib.Native.NativeLib.IsUnix()) form_tab_control.SelectTab(0); } @@ -102,8 +101,7 @@ private void child_view_show() { entry_is_child = false; buttons_show(); return; - } - + } init_child_vals(); } public static bool entry_is_in_template_group(IPluginHost m_host, PwGroup group) { diff --git a/KPEntryTemplates.cs b/KPEntryTemplates.cs index cfaa20c..990ce3f 100644 --- a/KPEntryTemplates.cs +++ b/KPEntryTemplates.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Threading.Tasks; using System.Windows.Forms; using KeePass.Forms; using KeePass.Plugins; +using KeePass.Resources; using KeePass.UI; using KeePass.Util; using KeePassLib; @@ -48,50 +50,38 @@ void GlobalWindowManager_WindowAdded(object sender, GwmWindowEventArgs e) { if (form == null) return; form.Shown += form_Shown; - form.Resize += form_Resize; + form.Resize += form_Resize; } - void form_Shown(object sender, EventArgs e) - { - PwEntryForm form = sender as PwEntryForm; - new EntryTemplateManager(m_host, form); - } - - void form_Resize(object sender, EventArgs e) - { - // on form resize, change edits and bottom button widths; - // also reposition right side buttons - - PwEntryForm form = sender as PwEntryForm; - - TabControl tabControl = null; - foreach (Control c in form.Controls) { - if (c is TabControl) { - tabControl = c as TabControl; - break; - } - } - if (tabControl == null) return; - - TabPage tmplPage = tabControl.TabPages[0]; - if (tmplPage.Text != "Template") return; - - foreach (Control c in tmplPage.Controls) { - if (!(c is Label)) { - if (c is CheckBox) { - c.Left = tmplPage.Width - ((c.Width + 55) / 2); - } else if (c is Button) { - if ((c as Button).Text == "Remove As Template Child") { - c.Width = tmplPage.Width - c.Left - 55; - } else { - c.Left = tmplPage.Width - ((c.Width + 55) / 2); - } - } else { - c.Width = tmplPage.Width - c.Left - 55; - } - } - } - } + private void form_Shown(object sender, EventArgs e) { + PwEntryForm form = sender as PwEntryForm; + new EntryTemplateManager(m_host, form); + //form_Resize(sender, e); + + } + + void form_Resize(object sender, EventArgs e) { + + + PwEntryForm form = sender as PwEntryForm; + + TabControl tabControl = null; + foreach (Control c in form.Controls) { + if (c is TabControl) { + tabControl = c as TabControl; + break; + } + } + if (tabControl == null) return; + + TabPage tmplPage = tabControl.TabPages[0]; + if (tmplPage.Text != "Template") + return; + EntryTemplateManager.SetBaseSizes(tmplPage); + foreach (Control c in tmplPage.Controls) + EntryTemplateManager.UpdateControlSize(c); + + } void EntryTemplates_EntryCreating(object sender, TemplateEntryEventArgs e) { EntryTemplateManager.InitChildEntry(e.TemplateEntry, e.Entry); @@ -115,7 +105,7 @@ void m_tsmi_set_template_parent_Click(object sender, EventArgs e) { return; PwEntry[] entries = m_host.MainWindow.GetSelectedEntries(); foreach (PwEntry entry in entries) { - EntryTemplateManager.set_entry_template_parent(m_host.Database,entry, parent); + EntryTemplateManager.set_entry_template_parent(m_host.Database, entry, parent); } m_host.MainWindow.UpdateUI(false, null, false, m_host.MainWindow.GetSelectedGroup(), false, null, true); } @@ -137,7 +127,7 @@ void EntryContextMenu_Opening(object sender, System.ComponentModel.CancelEventAr } public override string UpdateUrl { get { - return "http://mitchcapper.com/keepass_versions.txt?KPET"; + return "http://mitchcapper.com/keepass_versions.txt?KPET&KPV=" + PwDefs.VersionString; } } public override void Terminate() { diff --git a/KPEntryTemplates.csproj b/KPEntryTemplates.csproj index bbcccb8..107db4a 100644 --- a/KPEntryTemplates.csproj +++ b/KPEntryTemplates.csproj @@ -1,5 +1,5 @@  - + Debug AnyCPU @@ -10,7 +10,7 @@ Properties KPEntryTemplates KPEntryTemplates - v4.0 + v4.5.2 512 false diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 79424fe..49ba507 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("7.5.0.0")] -[assembly: AssemblyFileVersion("7.5.0.0")] +[assembly: AssemblyVersion("8.0.0.0")] +[assembly: AssemblyFileVersion("8.0.0.0")] diff --git a/README.md b/README.md index 791d9ea..e62f3f1 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,12 @@ KP Entry Templates for KeePass 2.x ================================= +## Warning: KeePass 2.39 significantly changed the password control. Version 7.8 and higher are only compatible with keepass 2.39 and higher. CHANGES ----- +- 8.0 High DPI support completely redone, complete re-work of KeePass resize support properly handle the UI. Multi-line textboxes also improved. +- 7.8 KeePass 2.39> support, better password confirmation support, breaks keepass support < 2.39. Rich Textbox support. +- 7.7 KeePassResize support thanks to @h-a-s-h - 7.6 ComboBox width fixed to full size (rather than smallest entry) - 7.5 Compatibility with KeePass 2.36 and better - 7.3 Added inline url option that has a clickable link to open the url @@ -17,7 +21,11 @@ OVERVIEW ----- KPEntryTemplates (KPET) is a plug-in that is supposed to make it easier for KeePass to be used for storing additional things than web logins and extend -the best templating system. The primary interface for the plug-in is an +the built in templating system by providing a UI. + +Bug reports and feature requests should be filed in GitHub while general discussion in https://gitter.im/KeePassUnofficial/Plugins + +The primary interface for the plug-in is an extra tab that shows up in the main Add Entry form. By default going to the tab on a new entry will present you with one of two buttons, "Init As Template" or "Set Template Parent". "Init As Template" shows up @@ -35,7 +43,7 @@ and is the actual field name the field is stored under. Finally, the of which are self explanatory. A few may require some explanation: - "Inline" is a standard textbox - +- "Rich Textbox" is a rich textbox (URL highlighting and such like the normal notes box). - "Popout" shows the standard custom field editing window - "Divider" is not a field at all, but rather can be used to section the diff --git a/Resources/Resources.Designer.cs b/Resources/Resources.Designer.cs index 6e3439f..203a1ab 100644 --- a/Resources/Resources.Designer.cs +++ b/Resources/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace KPEntryTemplates.Resources { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources {