2008-09-30 2 views
2

그래서 저는 윈도우 비헤이비어가 Photoshop CS와 비슷한 방식으로 동작하는 응용 프로그램을 가지고 있습니다. Photoshop CS에서 문서 창은 항상 도구 창 뒤에 있지만 최상위 창입니다. 문서 창은 실제로 자식이므로 MDI 자식 창에 대해서는 주 창 외부로 이동할 수 없습니다. 그러나 CS에서는 Visual Studio와 같은 도킹 된 응용 프로그램과 일반 MDI 응용 프로그램에 비해 이미지를 다른 모니터로 잘 옮길 수 있습니다.윈도우를 Photoshop CS와 같이 Z- 순서로 관리

어쨌든, 여기 내 연구가 있습니다. 나는 WM_MOUSEACTIVATE 메시지를 가로 채고 DeferWindowPos 명령을 사용하여 내 자신의 윈도우를 주문한 다음 MA_NOACTIVATEANDEAT를 반환하지만 윈도우가 제대로 활성화되지 못하게하고 "활성화시키는 다른 명령이 있다고 생각합니다. "WM_MOUSEACTIVATE (예 : SetFocus()) 호출하지 않고 창, 그래서 아마도 어쨌든 작동하지 않습니다.

나는 "활성화"에 대한 윈도우 프로 시저가 창 (WM_POSCHANGING, WM_POSCHANGED를 보내는 WM_NCACTIVATE 및 WM_ACTIVATE 메시지와 함께 2. 이동 Z 순서의 상단에 창을 활성화되지 않은 창을 통보하고 다시 칠 1 믿는다 메시지) 3. WM_NCACTIVATE 및 WM_ACTIVATE 메시지를 사용하여 새로 활성화 된 창에 알립니다.

첫 번째 WM_ACTIVATE 메시지를 가로채는 것이 가장 깨끗한 방법 인 것처럼 보이며 어떻게 든 Windows에 알리고 Z- 순서 지정 방식을 재정의 한 다음 DeferWindowPos 명령을 사용하지만 그렇게하는 법을 알 수 없습니다. 일단 Windows에서 WM_ACTIVATE 메시지를 보내면 이미 순서를 바꾸어 처리 할 것으로 보이므로 사용하는 모든 DeferWindowPos 명령이 재정의됩니다.

지금 당장은 앱 실행시 도구 창을 최상으로 만드는 기본적인 구현 방식을 사용하고 있지만 그렇지 않을 때는 최상위가되지 못하지만 매우 기발합니다 (때로는 맨 위에 표시됨). 작업 관리자와 같은 다른 창, Photoshop CS는 그렇게하지 않으므로 Photoshop이 어떻게 든 다르게 처리한다고 생각합니다.) 더 직관적 인 방법으로 작업하는 것처럼 보입니다.

어쨌든 Photoshop CS가 어떻게 작동하는지 또는 최상위를 사용하는 것보다 더 나은 방법을 알고 있습니까?

답변

-1

.NET을 사용하지 않기 때문에 오랜 시간에 걸쳐 자신의 윈도 잉 코드를 굴려서 Amazon의 원래 OBIDOS과 같아 졌으므로 지금은 오프라인 제품에 익숙해 져 있다고 생각합니다. The-Shelf (.NET의 MDI 지원이라고도 함)는 거의 끝나지 않을 것입니다.

나는 진짜 대답이 없으면 대답을 좋아하지 않지만, 과 비슷한 것을 얻으려면 많은 시간과 노력을 기울여야 만합니다. Photoshop과 같은 것이 진정으로 목표라면. 그것은 당신의 시간 가치가 있습니까? 많은 프로그래머가 이상이고 버전이 년이고 Photoshop의 단순한 모양의 창 작업이 제대로 작동하고 자연스럽게 느껴질 수 있습니다.

"솔루션"을 엿볼 수있는 Win32 API 함수와 값을 깊이 파고 드는 것처럼 보입니다. 첫 번째 빨간색 플래그가되어야합니다. 결국 가능할까요? 아마. 그러나 당신의 필요와 시간, 그리고 당신이 결정할 수있는 많은 다른 요소들에 따라, 그것은 실용적이지 않을 수도 있습니다.

+0

짧은 쪽지에서, 이것은 아마도 Poor-Man's-Photoshop 일명 김프 (내가 항상 사용하는 슬래 밍이 아닌)가 같은 종류의 창 작업을하지 않는 이유 일 수 있습니다. 실제로 김프를 사용하는 동안 내 주요 인물 중 하나입니다. Photoshop의 Mac 버전과 동일합니다. –

1

Photoshop CS에는 익숙하지 않아서 어떤 모양과 느낌을 얻으려고하는지 정확히 알기가 어렵습니다.

그러나 당신 도구 창으로 모덜리스 대화 상자 창을 생성하고 그 다음 결과 도구 창 메인 부모 윈도우 클리핑되지 않을 것 WS_POPUP 스타일을 가지고 확인했다 그리고 만약 내가 생각했을 것이다 Windows도구 창이 상위 창 위에 머무르도록 자동으로 관리합니다.

그리고 도구 창 대화 상자는 기본 창과 간섭하지 않으므로 도구 창입니다.

0

Managing Window Z-Order Like Photoshop CS

당신은 창문이 zOrder를 관리하도록 부모로서 이미지와 toolwindow을 만들어야합니다. WS_POPUP 또는 WS_EX_TOOLWINDOW를 설정할 필요가 없습니다. 이러한 플래그는 창의 렌더링 만 제어합니다.

이미지 창의 hwnd를 부모로 사용하여 CreateWindowEx를 호출하십시오.

3

Windows를 만들 때 올바른 소유자 윈도우 관계를 지정하는 것만으로는 해결할 수없는이 해킹 수준에 가까운 것이 무엇이든간에 Photoshop CS에 대한 주목할만한 것을 보지 못했습니다. 즉, 다른 윈도우 위에 표시되어야하는 모든 윈도우는 창을 만들 때 소유자로 지정합니다. - 여러 문서 윈도우가있는 경우 각각은 자신이 소유 한 자식 윈도우 세트를 가져옵니다.이 윈도우 윈도우는 문서 윈도우가 증가 할 때 동적으로 표시하거나 숨길 수 있습니다 활성화를 느슨하게합니다.

0

Chris와 Emmanuel에 대한 회신으로 소유자 창 기능을 사용할 때의 문제점은 창을 다른 창 하나에서만 소유 할 수 있으며 창을 소유 한 사람을 변경할 수 없다는 것입니다. 따라서 도구 창 A와 B가 항상 문서 창 C와 D의 맨 위에 있어야 할 경우, 문서 창 C가 활성화되면 창 A와 B를 소유하여 A와 B가 항상 맨 위에 오도록합니다. 그러나 문서 창 D를 활성화 할 때 도구 창 A와 B의 소유권을 D로 변경해야합니다. 그렇지 않으면 창 D가 창 C의 소유이기 때문에 창 D 뒤에 갈 것입니다. 그러나 Windows에서는 창의 소유권을 변경할 수 없으므로 해당 옵션을 사용할 수 없습니다.

현재로서는 최상위 기능으로 작업하고 있지만 해킹이 가장 좋습니다. 김프가 포토샵을 버전 2.6으로 에뮬레이트하려고 시도했지만, 구현이 가끔씩 이상하게 작동하여, 구현이 해킹이라고 생각하게 만듭니다.

0

주 창에 포커스가있을 때 도구 창을 최상으로 만들고 포커스를 잃었을 때 최상위가 아닌 도구 창을 만들려고 했습니까? 당신은 이미 이런 종류의 해결책을 보았던 것처럼 들리지만 훨씬 더 정교합니다.

참고로 z- 오더링과 관련하여 도구 창에 예기치 않은 동작이 나타나는 것으로 나타났습니다. 나는 그것을 확인하기 위해 MSDN에서 아무 것도 발견하지 못했다. 그러나 Windows가 특별하게 관리 할 수있다.

2

WM_WINDOWPOSCHANGING 이벤트를 처리하여 서로 다른 윈도우가 겹치는 것을 방지 할 수 있습니다 (가상 최상위 플래그 포함). 따라서 TopMost 플래그 설정/지우기와 관련된 모든 문제를 피할 수 있습니다.

public class BaseForm : Form 
{ 
    public virtual int TopMostLevel 
    { 
     get { return 0; } 
    } 

    [DllImport("user32.dll")] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool EnumThreadWindows(uint dwThreadId, Win32Callback lpEnumFunc, IntPtr lParam); 

    /// <summary> 
    /// Get process window handles sorted by z order from top to bottom. 
    /// </summary> 
    public static IEnumerable<IntPtr> GetWindowsSortedByZOrder() 
    { 
     List<IntPtr> handles = new List<IntPtr>(); 
     EnumThreadWindows(GetCurrentThreadId(), 
          (hWnd, lparam) => 
           { 
            handles.Add(hWnd); 
            return true; 
           }, IntPtr.Zero); 
     return handles; 
    } 


    protected override void WndProc(ref Message m) 
    { 
      if (m.Msg == (int)WindowsMessages.WM_WINDOWPOSCHANGING) 
      { 
       //Looking for Window at the bottom of Z-order, but with TopMostLevel > this.TopMostLevel 
       foreach (IntPtr handle in GetWindowsSortedByZOrder().Reverse()) 
       { 
        var window = FromHandle(handle) as BaseForm; 
        if (window != null && this.TopMostLevel < window.TopMostLevel) 
        { 
         //changing hwndInsertAfter field in WindowPos structure 
         if (IntPtr.Size == 4) 
         { 
          Marshal.WriteInt32(m.LParam, IntPtr.Size, window.Handle.ToInt32()); 
         } 
         else if (IntPtr.Size == 8) 
         { 
          Marshal.WriteInt64(m.LParam, IntPtr.Size, window.Handle.ToInt64()); 
         } 
         break; 
        } 
       } 
      } 

     base.WndProc(ref m); 
    } 
} 

public class FormWithLevel1 : BaseForm 
{ 
    public override int TopMostLevel 
    { 
     get { return 1; } 
    } 
} 

따라서 FormWithLevel1은 항상 모든 BaseForm을 덮어 씁니다. 임의의 수의 Z- 주문 레벨을 추가 할 수 있습니다.같은 레벨의 Windows는 평소와 같이 동작하지만 Windows에서는 항상 현재 + 1, Windows에서는 수준 Current-1입니다.

관련 문제