Author SHA1 Message Date
redlineoandClaude Sonnet 5 f1c67669fd Fix template list becoming unclickable with many entries via Dock layout
lstTemplates was a direct child of tabTemplates with an explicit pixel
Size, computed once against this dev machine's tab-strip height under
its own DPI/font scale. On the operator's real machine, adding enough
templates pushed rows past the control's actual bottom edge -
maximizing the window didn't help, confirming it wasn't a screen-space
problem but a stale size assumption baked into the designer file (the
same root cause as the earlier add/remove-button visibility bug).

Moved the button strip + list into their own panel (pnlTemplateList),
with the buttons Dock=Top and lstTemplates Dock=Fill - the list's
bounds are now computed by the layout engine against the real
container at runtime, with no absolute size to be wrong about,
regardless of DPI/font scale/window size.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 12:39:49 +03:00
@@ -35,6 +35,8 @@ namespace BulkArchiveMailer.AddIn.UI
private System.Windows.Forms.Label lblFromAccount;
private System.Windows.Forms.ComboBox cboFromAccount;
private System.Windows.Forms.Panel pnlTemplateList;
private System.Windows.Forms.Panel pnlTemplateButtons;
private System.Windows.Forms.ListBox lstTemplates;
private System.Windows.Forms.Button btnAddTemplate;
private System.Windows.Forms.Button btnRemoveTemplate;
@@ -80,6 +82,8 @@ namespace BulkArchiveMailer.AddIn.UI
this.lblFromAccount = new System.Windows.Forms.Label();
this.cboFromAccount = new System.Windows.Forms.ComboBox();
this.pnlTemplateList = new System.Windows.Forms.Panel();
this.pnlTemplateButtons = new System.Windows.Forms.Panel();
this.lstTemplates = new System.Windows.Forms.ListBox();
this.btnAddTemplate = new System.Windows.Forms.Button();
this.btnRemoveTemplate = new System.Windows.Forms.Button();
@@ -105,6 +109,8 @@ namespace BulkArchiveMailer.AddIn.UI
this.tabControl.SuspendLayout();
this.tabGeneral.SuspendLayout();
this.tabTemplates.SuspendLayout();
this.pnlTemplateList.SuspendLayout();
this.pnlTemplateButtons.SuspendLayout();
this.SuspendLayout();
//
@@ -213,9 +219,7 @@ namespace BulkArchiveMailer.AddIn.UI
this.tabTemplates.Text = "Шаблоны";
this.tabTemplates.Padding = new System.Windows.Forms.Padding(12);
this.tabTemplates.UseVisualStyleBackColor = true;
this.tabTemplates.Controls.Add(this.btnAddTemplate);
this.tabTemplates.Controls.Add(this.btnRemoveTemplate);
this.tabTemplates.Controls.Add(this.lstTemplates);
this.tabTemplates.Controls.Add(this.pnlTemplateList);
this.tabTemplates.Controls.Add(this.lblTplDisplayName);
this.tabTemplates.Controls.Add(this.txtTplDisplayName);
this.tabTemplates.Controls.Add(this.lblTplFileSuffix);
@@ -230,50 +234,74 @@ namespace BulkArchiveMailer.AddIn.UI
this.tabTemplates.Controls.Add(this.txtTplBody);
this.tabTemplates.Controls.Add(this.lblTplHint);
// btnAddTemplate / btnRemoveTemplate
// pnlTemplateList
//
// Deliberately placed ABOVE lstTemplates (not below it) so
// their visibility never depends on how much vertical room is
// left over at the bottom of the tab page after the list -
// that computation (tab-strip height under the operator's
// actual DPI/font scale, which this code cannot know at design
// time) is exactly what went wrong before: lstTemplates ran all
// the way to the tab page's real bottom edge with only ~6px to
// spare for the buttons beneath it, which was enough on some
// machines and not on others. Anchored Top|Left (fixed
// distance from the tab page's top-left corner) rather than
// Bottom, they are visible as long as the tab page itself is
// visible at all - not merely as long as it is "tall enough".
this.btnAddTemplate.Location = new System.Drawing.Point(15, 20);
// Left-column container for the template picker (buttons +
// list). Its own outer Location/Size/Anchor still use fixed
// pixel coordinates relative to the tab page, exactly like
// before - that outer placement was never the problem. What
// is Dock-based from here down is everything INSIDE this
// panel, which is the part that actually broke on a real
// machine: lstTemplates used to be a direct child of
// tabTemplates with an explicit Size, so its bottom edge (and
// therefore its scrollability/clickability once many
// templates were added) depended on a hand-computed pixel
// height that was only ever verified on the dev machine's own
// DPI/font scale. Docking removes that computation entirely -
// see pnlTemplateButtons/lstTemplates below.
this.pnlTemplateList.Location = new System.Drawing.Point(15, 20);
this.pnlTemplateList.Size = new System.Drawing.Size(190, 467);
this.pnlTemplateList.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
// Dock order matters here: pnlTemplateButtons (Dock=Top) is
// added FIRST, lstTemplates (Dock=Fill) SECOND, so the Fill
// control's layout is computed against whatever client area
// remains under the already-docked top strip.
this.pnlTemplateList.Controls.Add(this.pnlTemplateButtons);
this.pnlTemplateList.Controls.Add(this.lstTemplates);
// pnlTemplateButtons
//
// Fixed-height strip pinned to the top of pnlTemplateList.
// btnAddTemplate/btnRemoveTemplate live inside it at a fixed
// offset from ITS top-left corner (0,0)/(95,0) - a small,
// never-resized container, so plain Location placement here
// carries none of the earlier risk (that risk only existed
// when the same fixed coordinates were relative to the whole,
// variable-height tab page).
this.pnlTemplateButtons.Dock = System.Windows.Forms.DockStyle.Top;
this.pnlTemplateButtons.Size = new System.Drawing.Size(190, 35);
this.pnlTemplateButtons.Controls.Add(this.btnAddTemplate);
this.pnlTemplateButtons.Controls.Add(this.btnRemoveTemplate);
// btnAddTemplate
this.btnAddTemplate.Location = new System.Drawing.Point(0, 0);
this.btnAddTemplate.Size = new System.Drawing.Size(90, 27);
this.btnAddTemplate.Text = "+ Добавить";
this.btnAddTemplate.UseVisualStyleBackColor = true;
this.btnAddTemplate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)));
this.btnAddTemplate.Click += new System.EventHandler(this.btnAddTemplate_Click);
// btnRemoveTemplate
this.btnRemoveTemplate.Location = new System.Drawing.Point(115, 20);
this.btnRemoveTemplate.Location = new System.Drawing.Point(95, 0);
this.btnRemoveTemplate.Size = new System.Drawing.Size(90, 27);
this.btnRemoveTemplate.Text = "Удалить";
this.btnRemoveTemplate.UseVisualStyleBackColor = true;
this.btnRemoveTemplate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)));
this.btnRemoveTemplate.Click += new System.EventHandler(this.btnRemoveTemplate_Click);
// lstTemplates
//
// Starts below the two buttons now (y=55, was y=20) and still
// stretches down to the bottom of the tab page (Anchor
// Top|Bottom|Left) - only its OWN bottom edge is at risk of
// being visually tight against the tab page's real bottom
// edge if the assumed content height is off, which just means
// slightly less of the list is visible at once (it already has
// a scrollbar - IntegralHeight = false - so this degrades
// gracefully) rather than an entire control disappearing.
this.lstTemplates.Location = new System.Drawing.Point(15, 55);
this.lstTemplates.Size = new System.Drawing.Size(190, 432);
// Dock=Fill: always occupies exactly whatever area of
// pnlTemplateList is left below pnlTemplateButtons, computed
// by the layout engine at every resize/DPI - not a hand-picked
// pixel height that can end up too short (and therefore
// effectively unscrollable/unclickable for items past the cut
// -off) on a machine with different DPI/font scaling than the
// one this was last tested on. IntegralHeight = false just
// means the list doesn't force its height to a whole multiple
// of the item height - irrelevant to whether Fill can "escape"
// the panel, which it structurally cannot.
this.lstTemplates.Dock = System.Windows.Forms.DockStyle.Fill;
this.lstTemplates.IntegralHeight = false;
this.lstTemplates.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.lstTemplates.SelectedIndexChanged += new System.EventHandler(this.lstTemplates_SelectedIndexChanged);
// lblTplDisplayName
@@ -399,6 +427,8 @@ namespace BulkArchiveMailer.AddIn.UI
this.tabControl.ResumeLayout(false);
this.tabGeneral.ResumeLayout(false);
this.tabGeneral.PerformLayout();
this.pnlTemplateButtons.ResumeLayout(false);
this.pnlTemplateList.ResumeLayout(false);
this.tabTemplates.ResumeLayout(false);
this.tabTemplates.PerformLayout();
this.ResumeLayout(false);