기능 추가 Ctrl +Shift + P
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019WT2pzDE45iP4QMAAo7cyzmain
parent
9962c4e7dd
commit
e7f39a7bc1
149
Program.cs
149
Program.cs
|
|
@ -247,6 +247,64 @@ namespace WindowsKeyInfo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>제한 화면에서 Ctrl+Shift+P로 여는 마스터 암호 입력 창 (틀리면 알림 후 다시 입력)</summary>
|
||||||
|
internal sealed class MasterPasswordDialog : Form
|
||||||
|
{
|
||||||
|
private readonly TextBox _box;
|
||||||
|
|
||||||
|
public MasterPasswordDialog()
|
||||||
|
{
|
||||||
|
Text = "Windows Key";
|
||||||
|
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||||
|
MaximizeBox = false;
|
||||||
|
MinimizeBox = false;
|
||||||
|
ShowInTaskbar = false;
|
||||||
|
StartPosition = FormStartPosition.CenterParent;
|
||||||
|
AutoScaleMode = AutoScaleMode.Dpi;
|
||||||
|
Font = new Font("맑은 고딕", 9.5f);
|
||||||
|
ClientSize = new Size(360, 130);
|
||||||
|
|
||||||
|
var lbl = new Label
|
||||||
|
{
|
||||||
|
Text = "마스터 암호를 입력하세요.",
|
||||||
|
Location = new Point(14, 14),
|
||||||
|
Size = new Size(332, 22)
|
||||||
|
};
|
||||||
|
_box = new TextBox
|
||||||
|
{
|
||||||
|
Location = new Point(14, 42),
|
||||||
|
Size = new Size(332, 28),
|
||||||
|
UseSystemPasswordChar = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var btnOk = new Button { Text = "확인", Location = new Point(126, 84), Size = new Size(108, 32) };
|
||||||
|
btnOk.Click += (s, e) => TryAccept();
|
||||||
|
var btnCancel = new Button { Text = "취소", Location = new Point(240, 84), Size = new Size(106, 32), DialogResult = DialogResult.Cancel };
|
||||||
|
|
||||||
|
Controls.Add(lbl);
|
||||||
|
Controls.Add(_box);
|
||||||
|
Controls.Add(btnOk);
|
||||||
|
Controls.Add(btnCancel);
|
||||||
|
AcceptButton = btnOk;
|
||||||
|
CancelButton = btnCancel;
|
||||||
|
ActiveControl = _box;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TryAccept()
|
||||||
|
{
|
||||||
|
if (PasswordStore.Verify(_box.Text))
|
||||||
|
{
|
||||||
|
DialogResult = DialogResult.OK;
|
||||||
|
Close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageBox.Show(this, "암호가 틀렸습니다.", Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
_box.Clear();
|
||||||
|
_box.Focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>암호 변경 창 (새 암호 한 번 입력)</summary>
|
/// <summary>암호 변경 창 (새 암호 한 번 입력)</summary>
|
||||||
internal sealed class ChangePasswordDialog : Form
|
internal sealed class ChangePasswordDialog : Form
|
||||||
{
|
{
|
||||||
|
|
@ -409,15 +467,24 @@ namespace WindowsKeyInfo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>메인 창 (WinForms). fullMode=false면 키 정보 4줄 + 복사/파일로 저장/닫기만 표시</summary>
|
/// <summary>메인 창 (WinForms). 제한 모드면 키 정보 4줄 + 복사/파일로 저장/닫기만 표시,
|
||||||
|
/// 제한 모드에서 Ctrl+Shift+P → 마스터 암호 입력 → 맞으면 그 자리에서 전체 화면으로 전환</summary>
|
||||||
internal sealed class MainForm : Form
|
internal sealed class MainForm : Form
|
||||||
{
|
{
|
||||||
|
private const Keys UnlockShortcut = Keys.Control | Keys.Shift | Keys.P;
|
||||||
|
|
||||||
private readonly KeyReader.KeyInfo _info;
|
private readonly KeyReader.KeyInfo _info;
|
||||||
private readonly TextBox _txtProductName;
|
private readonly TextBox _txtProductName;
|
||||||
private readonly TextBox _txtProductId;
|
private readonly TextBox _txtProductId;
|
||||||
private readonly TextBox _txtInstalledKey;
|
private readonly TextBox _txtInstalledKey;
|
||||||
private readonly TextBox _txtBackupKey;
|
private readonly TextBox _txtBackupKey;
|
||||||
|
|
||||||
|
// 전체 모드에서만 보이는 컨트롤
|
||||||
|
private readonly Button _btnChangePw;
|
||||||
|
private readonly FlowLayoutPanel _phone;
|
||||||
|
private readonly FlowLayoutPanel _links;
|
||||||
|
private bool _fullMode;
|
||||||
|
|
||||||
public MainForm(bool fullMode)
|
public MainForm(bool fullMode)
|
||||||
{
|
{
|
||||||
Text = "Windows 제품 키 백업";
|
Text = "Windows 제품 키 백업";
|
||||||
|
|
@ -426,7 +493,7 @@ namespace WindowsKeyInfo
|
||||||
StartPosition = FormStartPosition.CenterScreen;
|
StartPosition = FormStartPosition.CenterScreen;
|
||||||
AutoScaleMode = AutoScaleMode.Dpi;
|
AutoScaleMode = AutoScaleMode.Dpi;
|
||||||
Font = new Font("맑은 고딕", 9.5f);
|
Font = new Font("맑은 고딕", 9.5f);
|
||||||
ClientSize = fullMode ? new Size(560, 344) : new Size(560, 240);
|
ClientSize = new Size(560, 344);
|
||||||
|
|
||||||
var table = new TableLayoutPanel
|
var table = new TableLayoutPanel
|
||||||
{
|
{
|
||||||
|
|
@ -465,20 +532,12 @@ namespace WindowsKeyInfo
|
||||||
buttons.Controls.Add(btnSave);
|
buttons.Controls.Add(btnSave);
|
||||||
buttons.Controls.Add(btnCopy);
|
buttons.Controls.Add(btnCopy);
|
||||||
|
|
||||||
if (fullMode)
|
_btnChangePw = MakeButton("암호 변경");
|
||||||
{
|
_btnChangePw.Click += (s, e) => ChangePassword();
|
||||||
var btnChangePw = MakeButton("암호 변경");
|
buttons.Controls.Add(_btnChangePw);
|
||||||
btnChangePw.Click += (s, e) => ChangePassword();
|
|
||||||
buttons.Controls.Add(btnChangePw);
|
|
||||||
}
|
|
||||||
|
|
||||||
Controls.Add(table);
|
|
||||||
Controls.Add(buttons);
|
|
||||||
|
|
||||||
if (fullMode)
|
|
||||||
{
|
|
||||||
// 화면 하단 바로가기 버튼 (기본 브라우저로 열기)
|
// 화면 하단 바로가기 버튼 (기본 브라우저로 열기)
|
||||||
var links = new FlowLayoutPanel
|
_links = new FlowLayoutPanel
|
||||||
{
|
{
|
||||||
Dock = DockStyle.Bottom,
|
Dock = DockStyle.Bottom,
|
||||||
FlowDirection = FlowDirection.LeftToRight,
|
FlowDirection = FlowDirection.LeftToRight,
|
||||||
|
|
@ -496,13 +555,13 @@ namespace WindowsKeyInfo
|
||||||
var btnGetCidInfo = MakeLinkButton("GETCID.INFO", "https://getcid.info/");
|
var btnGetCidInfo = MakeLinkButton("GETCID.INFO", "https://getcid.info/");
|
||||||
var btnGetCidUs = MakeLinkButton("GETCID.US", "https://getcid.us/");
|
var btnGetCidUs = MakeLinkButton("GETCID.US", "https://getcid.us/");
|
||||||
|
|
||||||
links.Controls.Add(lblLinks);
|
_links.Controls.Add(lblLinks);
|
||||||
links.Controls.Add(btnGetCidMe);
|
_links.Controls.Add(btnGetCidMe);
|
||||||
links.Controls.Add(btnGetCidInfo);
|
_links.Controls.Add(btnGetCidInfo);
|
||||||
links.Controls.Add(btnGetCidUs);
|
_links.Controls.Add(btnGetCidUs);
|
||||||
|
|
||||||
// 전화 인증 (slmgr 명령어 방식 — slui 4 창이 막혀 있어도 동작)
|
// 전화 인증 (slmgr 명령어 방식 — slui 4 창이 막혀 있어도 동작)
|
||||||
var phone = new FlowLayoutPanel
|
_phone = new FlowLayoutPanel
|
||||||
{
|
{
|
||||||
Dock = DockStyle.Bottom,
|
Dock = DockStyle.Bottom,
|
||||||
FlowDirection = FlowDirection.LeftToRight,
|
FlowDirection = FlowDirection.LeftToRight,
|
||||||
|
|
@ -520,9 +579,9 @@ namespace WindowsKeyInfo
|
||||||
var btnEnterCid = MakeActionButton("② 확인 ID 입력");
|
var btnEnterCid = MakeActionButton("② 확인 ID 입력");
|
||||||
btnEnterCid.Click += (s, e) => EnterConfirmationId();
|
btnEnterCid.Click += (s, e) => EnterConfirmationId();
|
||||||
|
|
||||||
phone.Controls.Add(lblPhone);
|
_phone.Controls.Add(lblPhone);
|
||||||
phone.Controls.Add(btnShowIid);
|
_phone.Controls.Add(btnShowIid);
|
||||||
phone.Controls.Add(btnEnterCid);
|
_phone.Controls.Add(btnEnterCid);
|
||||||
|
|
||||||
var tip = new ToolTip();
|
var tip = new ToolTip();
|
||||||
tip.SetToolTip(btnShowIid, "설치 ID(Installation ID)를 확인합니다 (slmgr /dti)");
|
tip.SetToolTip(btnShowIid, "설치 ID(Installation ID)를 확인합니다 (slmgr /dti)");
|
||||||
|
|
@ -532,10 +591,10 @@ namespace WindowsKeyInfo
|
||||||
tip.SetToolTip(btnGetCidUs, "https://getcid.us/");
|
tip.SetToolTip(btnGetCidUs, "https://getcid.us/");
|
||||||
|
|
||||||
// Dock=Bottom 은 나중에 추가한 것이 더 아래에 배치됨
|
// Dock=Bottom 은 나중에 추가한 것이 더 아래에 배치됨
|
||||||
Controls.Add(phone);
|
Controls.Add(table);
|
||||||
Controls.Add(links);
|
Controls.Add(buttons);
|
||||||
}
|
Controls.Add(_phone);
|
||||||
|
Controls.Add(_links);
|
||||||
CancelButton = btnClose;
|
CancelButton = btnClose;
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
@ -560,6 +619,44 @@ namespace WindowsKeyInfo
|
||||||
_txtProductId.Text = _info.ProductId;
|
_txtProductId.Text = _info.ProductId;
|
||||||
_txtInstalledKey.Text = _info.InstalledKey;
|
_txtInstalledKey.Text = _info.InstalledKey;
|
||||||
_txtBackupKey.Text = _info.BackupKey;
|
_txtBackupKey.Text = _info.BackupKey;
|
||||||
|
|
||||||
|
// 처음 표시 모드 (DPI 배율 적용 전이므로 기준 크기로 지정)
|
||||||
|
_fullMode = fullMode;
|
||||||
|
_btnChangePw.Visible = fullMode;
|
||||||
|
_phone.Visible = fullMode;
|
||||||
|
_links.Visible = fullMode;
|
||||||
|
ClientSize = new Size(560, fullMode ? 344 : 240);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>제한 모드 → 전체 모드 전환 (실행 중, DPI 배율이 적용된 실제 크기 기준으로 창 높이 증가)</summary>
|
||||||
|
private void SwitchToFullMode()
|
||||||
|
{
|
||||||
|
if (_fullMode) return;
|
||||||
|
_fullMode = true;
|
||||||
|
|
||||||
|
float scale = _phone.Height / 44f; // 현재 DPI 배율
|
||||||
|
int extra = _phone.Height + _links.Height + (int)Math.Round(10 * scale); // 344 - 240 = 104 = 44 + 50 + 10
|
||||||
|
|
||||||
|
SuspendLayout();
|
||||||
|
_btnChangePw.Visible = true;
|
||||||
|
_phone.Visible = true;
|
||||||
|
_links.Visible = true;
|
||||||
|
ClientSize = new Size(ClientSize.Width, ClientSize.Height + extra);
|
||||||
|
ResumeLayout(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>제한 모드에서 Ctrl+Shift+P → 마스터 암호 입력 창</summary>
|
||||||
|
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
|
||||||
|
{
|
||||||
|
if (keyData == UnlockShortcut && !_fullMode)
|
||||||
|
{
|
||||||
|
using (var dlg = new MasterPasswordDialog())
|
||||||
|
{
|
||||||
|
if (dlg.ShowDialog(this) == DialogResult.OK) SwitchToFullMode();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return base.ProcessCmdKey(ref msg, keyData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TextBox AddRow(TableLayoutPanel table, int row, string caption, bool monospace)
|
private static TextBox AddRow(TableLayoutPanel table, int row, string caption, bool monospace)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue