Message Loop

ν•œ 달에 ν•œλ²ˆμ€ 글을 써야지 ν•˜λŠ” λ§ˆμŒμœΌλ‘œβ€¦
뭘 쓸지 κ³ λ―Όν•˜λ‹€ μ–Όλ§ˆ μ „ κ°œλ°œν•œ λ‚΄μš©μ„ 곡유 λ“œλ¦΄κΉŒ ν•©λ‹ˆλ‹€.

이번 μ£Όμ œλŠ” 닷넷인듯 λ‹·λ„·μ•„λ‹Œ 닷넷같은 주제인데 μ•½κ°„ ꡐ양 μˆ˜μ€€μœΌλ‘œ 봐주셔도 되고
λ§ˆμ§€λ§‰μ— 이걸 μ•Œλ©΄ 이런걸 μ’€ 더 잘 μ΄ν•΄ν• μˆ˜ μžˆλ‹€ ν•˜λŠ” λ‚΄μš©λ„ μžˆμœΌλ‹ˆ μ°Έκ³ ν•΄ μ£Όμ‹œκΈ° λ°”λžλ‹ˆλ‹€.

ν”„λ‘œκ·Έλž¨μ„ λ§Œλ“€ λ•Œ μ»¨νŠΈλ‘€μ„ λ§Œλ“€κ³  κ°œλ°œν•˜λ©΄ λ‹Ήμ—°ν•˜λ‹€ μƒκ°ν•˜λŠ” 뢀뢄듀이 μžˆμŠ΅λ‹ˆλ‹€.
그렀지고, 클릭되고, μ΄λ™ν•˜κ³  κ·ΈλŸ°κ²ƒλ“€μ΄μ£ .

이 λͺ¨λ‘κ°€ λ‹Ήμ—°ν•˜κ²Œ λ˜λŠ” κ²ƒλ“€μ΄μ§€λ§Œ μ‹€μ œλ‘  μ’€ 더 λ³΅μž‘ν•œ ꡬ쑰가 μˆ¨μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

μš°μ„  WPFκ°€ μ‚¬μš©ν•˜λŠ” OS(Operating system) 즉 Windows에 λŒ€ν•΄μ„œ 쑰금 μ•Œκ³  갈 ν•„μš”κ°€ μžˆμŠ΅λ‹ˆλ‹€.
일반적으둜 OSλŠ” SDK(Software development kit)λ₯Ό μ œκ³΅ν•΄ μ€λ‹ˆλ‹€.
Windows 의 경우 SDKλ₯Ό Cμ–Έμ–΄λ‘œ 제곡 ν•˜κ³  있고 κ·Έ μ•ˆμ—λŠ” μ—¬λŸ¬ λΌμ΄λΈŒλŸ¬λ¦¬μ™€ ν—€λ”νŒŒμΌμ΄ μžˆμŠ΅λ‹ˆλ‹€.

그리고 κ·Έ ν—€λ”νŒŒμΌμ— μ„ μ–Έ λ˜μ–΄ μžˆλŠ” ν•¨μˆ˜λ“€μ„ API(Application Programming Interface)라고 ν•©λ‹ˆλ‹€.
그것듀을 ν†΅ν•΄μ„œ μš°λ¦¬λŠ” ν”„λ‘œκ·Έλž¨μ„ κ°œλ°œν• μˆ˜ μžˆμŠ΅λ‹ˆλ‹€.

이런 WinAPI λ₯Ό ν†΅ν•΄μ„œ λ§Œλ“œλŠ” κ°„λ‹¨ν•œ μƒ˜ν”Œμ€ VSμ—μ„œ μ œκ³΅ν•΄ μ€λ‹ˆλ‹€.
image

μ•ˆμ— μžˆλŠ” μ—¬λŸ¬ μ†ŒμŠ€ μ€‘μ—μ„œ μš°λ¦¬κ°€ 봐야 ν•  것은 단 7μ€„μž…λ‹ˆλ‹€.

    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

Windows μ—μ„œ λͺ¨λ“  ν”„λ‘œκ·Έλž¨μ€ 각자의 메세지 큐λ₯Ό 가지고 있고
OSλŠ” ν•΄λ‹Ή ν”„λ‘œκ·Έλž¨μ— λ§žλŠ” 메세지λ₯Ό 큐에 λ„£μ–΄ μ€λ‹ˆλ‹€.
ν”„λ‘œκ·Έλž¨μ€ μžμ‹ μ˜ 메세지 큐에 메세지가 λ“€μ–΄ 였면
그것을 κ°€μ Έλ‹€κ°€ 메세지에 λ§žλŠ” λ™μž‘μ„ ν•©λ‹ˆλ‹€.

WPFλŠ” 그런 λ³΅μž‘ν•œ λ‚΄μš©λ“€μ„ 객체지ν–₯적으둜 잘 λΆ„λ¦¬ν•˜κ³ 
λž©ν•‘ν•˜μ—¬ μ“°λŠ”μ‚¬λžŒμ—κ²Œ νŽΈμ˜μ„±μ„ μ œκ³΅ν•˜λŠ” ν”„λ ˆμž„μ›Œν¬μž…λ‹ˆλ‹€.

즉, APIλ₯Ό μ•ˆμ“°λŠ”κ²Œ μ•„λ‹ˆλΌ 내뢀에 숨겨 놓은 κ²λ‹ˆλ‹€.

μ‹€μ œ μ½”λ“œλ‘œ 보면 Dispatcher μ—μ„œ λ™μž‘ν•˜λŠ” 걸둜 λ³΄μ΄λ„€μš”.

말이 κΈΈμ–΄ μ‘ŒλŠ”λ° κ°„λ‹¨νžˆ μ •λ¦¬ν•˜λ©΄
Windowsμ—μ„œλŠ” λͺ¨λ“  이벀트 μ²˜λ¦¬λŠ” 메세지큐에 μžˆλŠ” 메세지λ₯Ό
νŽŒν•‘ν•΄μ„œ 처리 ν•œλ‹€. 이λ₯Ό 메세지 루프라고 λΆ€λ₯Έλ‹€

μž…λ‹ˆλ‹€.

그럼 λ§ˆμ§€λ§‰μœΌλ‘œ 이걸 μ™œ μ•Œμ•„μ•Ό λ˜λƒ? μž…λ‹ˆλ‹€.
WPFκ°€ λͺ¨λ“  APIλ₯Ό λž©ν•‘ν•΄ λ†”μ„œ WPF κΈ°λ³Έ κΈ°λŠ₯으둜
Windows의 λͺ¨λ“  κΈ°λŠ₯을 μ“Έμˆ˜ μžˆλ‹€λ©΄ μœ„ λ‚΄μš©μ€ λͺ°λΌλ„ 상관이 μ—†μŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ λͺ‡λͺ‡ κΈ°λŠ₯에 λŒ€ν•΄μ„œλŠ” 아직 지원 λ˜μ§€ μ•ŠλŠ” λ‚΄μš©μ΄ μžˆμŠ΅λ‹ˆλ‹€.

κ°€μž₯ λŒ€ν‘œμ μΈ 예둜 Clipboard Change μž…λ‹ˆλ‹€.

μžμ‹ μ΄ λ§Œλ“€ ν”„λ‘œκ·Έλž¨μ—μ„œ Windows 의 ν΄λ¦½λ³΄λ“œλ₯Ό μ“°λŠ” κ²½μš°κ°€ μžˆμ„μˆ˜ μžˆμŠ΅λ‹ˆλ‹€.
.net core WPFμ—μ„œ ν΄λ¦½λ³΄λ“œλ₯Ό μ“Έλ•ŒλŠ” System.Windows.Clipboard 클래슀λ₯Ό ν†΅ν•΄μ„œ
ν΄λ¦½λ³΄λ“œμ— 데이터λ₯Ό μ“°κ³  읽을 수 μžˆμŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ ν΄λ¦½λ³΄λ“œκ°€ λ³€κ²½λ˜μ—ˆμ„λ•Œ μ•Œλ¦Όμ„ λ°›μ„μˆ˜ μžˆλŠ” κΈ°λŠ₯은 아직 κ΅¬ν˜„ λ˜μ–΄ μžˆμ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
λ©”λͺ¨μž₯μ—μ„œ 글씨가 볡사 λ˜μ—ˆμ„λ•Œ λ‚΄μͺ½μ—μ„œλŠ” λΆ™μ—¬ λ„£λŠ” 데이터가 μžˆλ‹€λŠ”κ±Έ μ•Œμ•„μ•Ό ν• μˆ˜ μžˆμŠ΅λ‹ˆλ‹€.

ν•΄λ‹Ή κΈ°λŠ₯을 κ΅¬ν˜„ν•œ 예λ₯Ό 보여 λ“œλ¦¬κ² μŠ΅λ‹ˆλ‹€.

    [DllImport("User32.dll")]
    public static extern IntPtr SetClipboardViewer(IntPtr hWnd);
//........
    WindowInteropHelper helper = new(this);
    HwndSource.FromHwnd(hWnd).AddHook(new HwndSourceHook(WndProc));
    next = SetClipboardViewer(hWnd);
// .......
private nint WndProc(nint hwnd, int msg, nint wParam, nint lParam, ref bool handled)
{
    switch ((User32.WindowMessage)msg)
    {
        case User32.WindowMessage.WM_CHANGECBCHAIN:
            if (wParam == next)
                next = lParam;
            else if (next != 0)
                User32.SendMessage(next, (User32.WindowMessage)msg, wParam, lParam);
            break;
        case User32.WindowMessage.WM_DRAWCLIPBOARD:
            ClipboardChanged();
            User32.SendMessage(next, (User32.WindowMessage)msg, wParam, lParam);
            break;
    }
    return IntPtr.Zero;
}

μœ„μ—μ„œ 말씀 λ“œλ¦° λ©”μ„Έμ§€λ£¨ν”„λ‚˜ λ„ˆλ¬΄ κΈΈμ–΄μ„œ λΊ€ WndProc 같은걸 μ–΄λŠ 정도
μ΄ν•΄λ§Œ ν•˜κ³  κ³„μ‹œλ©΄ 이런 λ¬Έμ œκ°€ μƒκ²Όμ„λ•Œ
검색 된 μ†ŒμŠ€λ₯Ό 보고 이해 ν•˜λŠ”λ° 도움이 λ˜μ‹€κ±° κ°™λ„€μš”.

9개의 μ’‹μ•„μš”

μœˆλ„μš° ν”„λ‘œκ·Έλž˜λ°μ„ κ²½ν—˜ν•˜μ§€ λͺ»ν–ˆκ³ , Cλ‚˜ C++ 에 μΌμžλ¬΄μ‹μ— κ°€κΉŒμš΄ 저도 μ΄ν•΄ν•˜κΈ° 맀우 μ‰¬μš΄ 것 κ°™μŠ΅λ‹ˆλ‹€.쒋은 κΈ€ κ°μ‚¬ν•©λ‹ˆλ‹€.

그런데, μ•„λž˜μ˜ μΌ€μ΄μŠ€λŠ” μ„ λœ» μ΄ν•΄ν•˜κΈ° 쉽지 μ•Šμ€ 것 κ°™μŠ΅λ‹ˆλ‹€.

λ‚΄ 앱은 κ·Έλƒ₯ ν‚€λ³΄λ“œ 이벀트(ctrl+v)λ₯Ό 받을 λ•Œλ§Œ ν΄λ¦½λ³΄λ“œλ₯Ό μ—΄λžŒν•˜λ©΄ λ˜μ§€ μ•Šλ‚˜μš”?
μ‹œμŠ€ν…œμ—μ„œ μΌμ–΄λ‚˜λŠ” λͺ¨λ“  ν΄λ¦½λ³΄λ“œ 이벀트λ₯Ό μ²˜λ¦¬ν•œλ‹€λŠ” 게 μ„ λœ» μ΄ν•΄λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

λ‚΄ 앱이 ν΄λ¦½λ³΄λ“œ 관리 ν”„λ‘œκ·Έλž¨μ΄ μ•„λ‹Œλ°λ„, ν΄λ¦½λ³΄λ“œ 이벀트λ₯Ό λ°›μ•„μ•Ό ν•˜λŠ” 경우라면 μ–΄λ–€ 게 μžˆμ„κΉŒμš”? μ‹€λ¬΄μ μœΌλ‘œ κ²½ν—˜ν•œ 것이 μžˆλ‹€λ©΄ κ³΅μœ λΆ€νƒλ“œλ¦½λ‹ˆλ‹€.

6개의 μ’‹μ•„μš”

[ν‹€λ¦° κ·Έλ¦Ό μ°ΎκΈ°]
image
image

μš”λ ‡κ²Œ μ˜€ν”ΌμŠ€μ˜ κ²½μš°μ—λ„ λΆ™μ—¬λ„£κΈ° κ°€λŠ₯ ν• λ•Œμ™€ λΆˆκ°€λŠ₯ ν• λ•Œ μ•„μ΄μ½˜μ΄ λ‹€λ¦…λ‹ˆλ‹€.

저희 μ œν’ˆλ„ λ§ˆμ°¬κ°€μ§€ μΈλ°μš”


Ctrl+V 이전에 ν΄λ¦½λ³΄λ“œ 체인지λ₯Ό 감지 ν•˜μ—¬
CanExecute λ₯Ό μ²˜λ¦¬ν•΄ μ£Όλ©΄ μ’€ 더 μ•ˆμ •μ μ΄κ³  λΆˆν•„μš”ν•œ λ™μž‘μ„ μ˜ˆλ°©ν• μˆ˜ μžˆμŠ΅λ‹ˆλ‹€.

μΆ”κ°€λ‘œ ClipBoardμ—λŠ” μ—¬λŸ¬ νƒ€μž…μ˜ 데이터가 λ“€μ–΄ 올 수 μžˆμŠ΅λ‹ˆλ‹€.

이것에 λŒ€ν•΄μ„œλ„ 미리 νŒλ‹¨ ν•˜μ—¬ μš°λ¦¬κ°€ λ°›μ•„ 듀일 νƒ€μž…μΈμ§€,
μ•„λ‹Œμ§€λ„ μ•Œμˆ˜ μžˆμŠ΅λ‹ˆλ‹€.

8개의 μ’‹μ•„μš”

호였!! :heart_eyes:

4개의 μ’‹μ•„μš”

μ—­μ‹œ μΊλ“œ μ’…λ₯˜ ν”„λ‘œκ·Έλž¨μ€ WPFλ₯Ό 베이슀둜 ν•˜λŠ”κ²Œ 'μ™€λ”°β€™κ°™λ„€μš”β€¦
μ—„μ²­λ‚©λ‹ˆλ‹€β€¦