여기 FontDialog
의 행동의 주요 기능은 부모 (소유자) 관계에 있지만, 사실은 아니지만 ... 단지 ShowDialog
에 매개 변수로 바탕 화면 핸들에 보내 작동 할 수 있습니다 ShowDialog
으로 만 호출 할 수 있으며 GUI 스레드를 차단하지 않고도이를 수행 할 분명한 방법은 없습니다.
다행히도이 문제를 해결하기 위해 이입니다. BackgroundWorker
을 사용하여 ShowDialog
에 대한 호출을 작업자 스레드에 분로 뽑아 GUI 스레드가 진행되도록했습니다. 비동기 FontDialog
래퍼 클래스는 다음과 같습니다
public class FontDialogAsync
{
public event EventHandler<NewFontChosenEventArgs> NewFontChosen;
private readonly IWin32Window parentHandle;
private readonly BackgroundWorker fontDialogWorker = new BackgroundWorker();
private class WindowWrapper : IWin32Window
{
public WindowWrapper(IntPtr hWnd)
{
Handle = hWnd;
}
public IntPtr Handle { get; private set; }
}
public FontDialogAsync(IWin32Window parent)
{
parentHandle = new WindowWrapper(parent.Handle);
fontDialogWorker.DoWork += FontDialogWorkerDoWork;
fontDialogWorker.RunWorkerCompleted += FontDialogWorkerRunWorkerCompleted;
}
private class FontDialogAsyncArgs
{
public readonly IWin32Window ParentForm;
public readonly Font InitialFont;
public FontDialogAsyncArgs(IWin32Window parent, Font initFont)
{
ParentForm = parent;
InitialFont = initFont;
}
}
public void Show(Font font)
{
if (!fontDialogWorker.IsBusy) fontDialogWorker.RunWorkerAsync(new FontDialogAsyncArgs(parentHandle, font));
}
private static void FontDialogWorkerDoWork(object sender, DoWorkEventArgs e)
{
try
{
var args = (FontDialogAsyncArgs)e.Argument;
var fontDialog = new FontDialog { Font = args.InitialFont };
var result = fontDialog.ShowDialog(args.ParentForm);
e.Result = (result == DialogResult.Cancel) ? null : fontDialog.Font;
}
catch (Exception ex)
{
UtilitiesAndConstants.ReportExceptionToCommonLog(ex);
}
}
private void FontDialogWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e1)
{
if (e1.Result == null) return;
if (NewFontChosen != null) NewFontChosen(this, new NewFontChosenEventArgs((Font)e1.Result));
}
}
[당신이 크로스 스레드 예외를 발생에서 런타임을 유지하기 위해 WindowWrapper
예를 내부의 부모 창 핸들을 숨길 필요가 있습니다.]
EventArgs
public class NewFontChosenEventArgs : EventArgs
{
public readonly Font FontChosen;
public NewFontChosenEventArgs(Font newFont)
{
FontChosen = newFont;
}
}
을 ... 그리고 당신은 다음과 같이 사용 : 클래스는 다음과 같습니다
private FontDialogAsync nonBlockingFontDialog;
public void SetFont()
{
if (nonBlockingFontDialog == null)
{
nonBlockingFontDialog = new FontDialogAsync(ParentForm);
nonBlockingFontDialog.NewFontChosen += NonBlockingFontDialogNewFontChosen;
}
nonBlockingFontDialog.Show(Font);
}
여기서 ParentForm
은 대화 상자를 연결하려는 Windows.Form
인스턴스입니다. 결과 대화 상자는 부모와 관련하여 모달입니다 (대화 상자를 먼저 닫지 않고 부모와 아무 것도 할 수 없음). 그러나 나머지 appliation UI는 정상적으로 작동합니다.
OP의 설명이 나에게 잘못되었습니다. 글꼴 대화 상자가 모달이고 다른 창을 사용할 수없는 경우 글꼴 대화 상자의 다른 창은 어떻게 나타 납니까? –
'사용 중지'되어 있지 않습니다. 클릭에 응답하지 않습니다. 작업 표시 줄 아이콘 (사용자가 일반적으로 모달 대화 상자를 잃어 버렸을 때 일반적으로하는 작업)을 사용하여 그 중 하나를 앞에 가져올 수 있습니다. – McKenzieG1
@Rusty - 좋은 제안이지만 내 팀에게는 좋은 투자가 아닐 수도 있습니다. 우리는 커스터마이징이 가능한 글꼴을 많이 사용하지 않으며, 글꼴 선택 도구는 다소 복잡한 대화 상자입니다. – McKenzieG1