2010-05-27 4 views
1

WinForms "글꼴 선택기"대화 상자를 모달이 아닌 방식으로 표시 할 수 있습니까? 또는 모달이 아닌 방식으로 사용할 수있는 표준 글꼴 외의 다른 글꼴 선택 도구가 있습니까?넌 모달 WinForms FontDialog?

우리의 응용 프로그램에는 많은 창과 작업을 방해하고 뭔가를보기 위해 다른 창으로 전환해야하는 사용자가 있습니다. 창을 전환하는 데 작업 표시 줄 단추를 사용하는 경우 UI가 응답하지 않는 모달 대화 상자가있는 "묻힌 대화 상자"시나리오로 이어지는 경향이 있지만 포커스를 캡처 한 모달 대화 상자가 뒤에 있기 때문에 즉시 알 수 없습니다 다른 창.

+0

OP의 설명이 나에게 잘못되었습니다. 글꼴 대화 상자가 모달이고 다른 창을 사용할 수없는 경우 글꼴 대화 상자의 다른 창은 어떻게 나타 납니까? –

+0

'사용 중지'되어 있지 않습니다. 클릭에 응답하지 않습니다. 작업 표시 줄 아이콘 (사용자가 일반적으로 모달 대화 상자를 잃어 버렸을 때 일반적으로하는 작업)을 사용하여 그 중 하나를 앞에 가져올 수 있습니다. – McKenzieG1

+0

@Rusty - 좋은 제안이지만 내 팀에게는 좋은 투자가 아닐 수도 있습니다. 우리는 커스터마이징이 가능한 글꼴을 많이 사용하지 않으며, 글꼴 선택 도구는 다소 복잡한 대화 상자입니다. – McKenzieG1

답변

0

여기 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는 정상적으로 작동합니다.

1

정확한 코드는 모르지만 데스크톱은 Owner으로 바꿔야합니다. OwnerFontDialog에서 상속 사용자 정의 클래스를 생성하는 것입니다 설정

http://www.pinvoke.net/default.aspx/user32.getdesktopwindow

한 가지 방법은 다음 소유자를 설정 : 여기에 설명 된대로 GetDesktopWindow API 방법을 사용하여 바탕 화면에 핸들을 얻을 수 있습니다 protectedCommonDialog.RunDialog 방법을 사용하는 것이지만 다른 방법 일 수도 있습니다.

편집 : 사실,

관련 문제