10.1(월) 실습-1

2007/10/13 12:04

1. 트레이에 ICON 넣기 & 시스템 메뉴에 항목추가하기

[ more.. | less.. ]
//-------------------------------------------------------------------------------
// 시스템 메뉴의 ID 16의 배수로 0xF000 보다 작게...

#define IDM_SYS_TOPMOST 0x0010
#define WM_TRAYMESSAGE    WM_USER+100
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch( msg )
    {   
    case WM_CREATE:
        {
            // 시스템 메뉴의 핸들을 얻어낸다.
            HMENU hMenu = GetSystemMenu( hwnd, FALSE );
            // 메뉴를 추가한다.
            AppendMenu( hMenu, MF_SEPARATOR, 0, 0 );
            AppendMenu( hMenu, MF_STRING, IDM_SYS_TOPMOST, "항상위" );
        }       
        return 0;
    case WM_SYSCOMMAND:
        // 주의 ID 조사시 하위 4비트를 0으로 놓고 조사한다.
        switch( LOWORD( wParam & 0xFFF0 ) )
        {
        case IDM_SYS_TOPMOST:
            MessageBox( hwnd, "항상위", "", MB_OK );
            return 0;
        case SC_MINIMIZE:    // 닫기 메뉴의 ID
            {
                // 트레이에 Icon 넣기.
                NOTIFYICONDATA nid = { 0 };
                nid.cbSize = sizeof(nid);
                nid.hIcon = LoadIcon( 0, IDI_WINLOGO );
                nid.hWnd = hwnd;

                nid.uCallbackMessage = WM_USER+100;
                nid.uID = 1;

                strcpy( nid.szTip, "Test" );

                nid.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;

                Shell_NotifyIcon( NIM_ADD, &nid );

                // 애니메이션 효과를 낸다..
                RECT rcFrom;
                GetWindowRect( hwnd, &rcFrom );

                // 실제로는 작업표시줄을 구해야 한다.
                RECT rcTo = { 1280, 1024, 1281, 1025 }; //화면 오른쪽 아래

                DrawAnimatedRects( hwnd, IDANI_CAPTION, &rcFrom, &rcTo );
               
                // 이제 윈도우를 숨긴다.
                ShowWindow( hwnd, SW_HIDE );
            }
            return 0;
        }
        // 나머지 모든 메뉴를 처리하기 위해 아래로 보내야 한다.
        return DefWindowProc( hwnd, msg, wParam, lParam );

    case WM_TRAYMESSAGE:
        if( wParam == 1 ) // Icon ID
        {
            if( lParam == WM_LBUTTONDBLCLK)
            {
                ShowWindow( hwnd, SW_SHOW );
            }
            else if( lParam == WM_RBUTTONUP )
            {
                // Context Menu 를 나타나게 해준다.
            }
        }
        return 0;

    case WM_LBUTTONDOWN:
        //GetSystemMenu( hwnd, TRUE );    // 초기상태로 되돌린다.
        return 0;

    case WM_DESTROY:
        // Tray Icon을 제거하고 종료해야 한다.
        {
            NOTIFYICONDATA nid = { 0 };
            nid.cbSize = sizeof(nid);
            nid.hWnd = hwnd;
            nid.uID = 1;
            Shell_NotifyIcon( NIM_DELETE, &nid );
        }
        PostQuitMessage(0);
        return 0;
    }

2. 커서 모양 바꾸기
[ more.. | less.. ]
//////////////////////////////////////////////////////////////////////////////////////
    HCURSOR hCursor = LoadCursor( hInstance, MAKEINTRESOURCE( IDC_CURSOR1 ) );
    // 애니메이션 커서 Load
    HCURSOR hCursor = LoadCursorFromFile( "C:\\windows\\cursors\\dinosaur.ani" );
//////////////////////////////////////////////////////////////////////////////////////
// 커서 위치별 변화시키기

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static HCURSOR h1 = LoadCursorFromFile( "C:\\windows\\cursors\\sizens.ani" );
    static HCURSOR h2 = LoadCursorFromFile( "C:\\windows\\cursors\\sizewe.ani" );
    static HCURSOR h3 = LoadCursorFromFile( "C:\\windows\\cursors\\banana.ani" );

    static RECT gameRect = { 10, 10, 100, 100 };

    switch( msg )
    {   
    case WM_SETCURSOR:
        {
            UINT code = LOWORD( lParam );

            POINT pt;
            GetCursorPos(&pt);
            ScreenToClient( hwnd, &pt );

            if ( code == HTCLIENT && PtInRect( &gameRect, pt ) )
            {
                SetCursor( h3 );
                return TRUE;
            }

            if ( code == HTTOP || code == HTBOTTOM )
            {
                SetCursor( h1 );
                return TRUE;    // 커서변경한 경우 TRUE 리턴
            }
            if ( code == HTLEFT || code == HTRIGHT )
            {
                SetCursor( h2 );
                return TRUE;
            }

        }
        return DefWindowProc( hwnd, msg, wParam, lParam );

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc( hwnd, msg, wParam, lParam);
}

3. DragDrop 구현( 파일이름 읽어오기 )

[ more.. | less.. ]
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch( msg )
    {   
        // 탐색기가 보내주는 메세지
    case WM_DROPFILES:
        {
            // Drop된 파일의 이름을 가진 메모리 핸들을 얻어 낸다.
            HDROP hDrop = (HDROP)wParam;

            // 먼저 갯수를 파악한다.
            int count = DragQueryFile( hDrop, -1, 0, 0 );

            for ( int i = 0; i < count; ++i )
            {
                // 파일의 이름을 꺼낸다.
                char name[256] = { 0 };
                DragQueryFile( hDrop, i, name, 256 );

                MessageBox( 0, name, "", MB_OK );
            }
            //DragDrop을 종료한다.
            DragFinish( hDrop );
        }
        return 0;
    case WM_CREATE:
        DragAcceptFiles( hwnd, TRUE );
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc( hwnd, msg, wParam, lParam);
}

4. spy++ UI 따라해보기( ALT+TAB 버그 수정해보기 )

[ more.. | less.. ]
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static HCURSOR    hCursor;
    static HICON    hFill, hEmpty;
    static RECT        rc = { 10, 10, 42, 42 };
    static HINSTANCE hInstance;

    switch( msg )
    {   
    case WM_CREATE:
        hInstance = ((LPCREATESTRUCT)lParam)->hInstance;

        hCursor = LoadCursor( hInstance, MAKEINTRESOURCE(IDC_CURSOR1) );
        hFill    = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_ICON1) );
        hEmpty    = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_ICON2) );

        return 0;

    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint( hwnd, &ps );
            DrawIcon( hdc, rc.left, rc.top, hFill );
            EndPaint( hwnd, &ps );
        }
        return 0;
    case WM_LBUTTONDOWN:
        {
            POINT pt = { LOWORD( lParam ), HIWORD( lParam ) };

            if( PtInRect( &rc, pt ) )
            {
                SetCursor( hCursor );
                SetCapture( hwnd );

                HDC hdc = GetDC( hwnd );
                DrawIcon( hdc, rc.left, rc.top, hEmpty );
                ReleaseDC( hwnd, hdc );
            }
        }
        return 0;
    case WM_LBUTTONUP:
        if( GetCapture() == hwnd )
        {
            ReleaseCapture();
            //InvalidateRect( hwnd, &rc, TRUE );
        }
        return 0;

        // 알트탭을 누르면 캡쳐상태가 풀리지만 다시 그리지 못한다. 이를 위해서
        // 캡쳐상태가 변경됬을떄 다시 그려주도록 한다.
    case WM_CAPTURECHANGED:
        {
            InvalidateRect( hwnd, &rc, TRUE );
        }
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }

5. 실행시간에 ICON을 변경, 윈도우 클래스도 변경!!
[ more.. | less.. ]
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static HBRUSH hBrush = CreateSolidBrush( RGB(255, 0, 0) );
    static HICON hIcon = LoadIcon( GetModuleHandle(0), "aaa" );
    static HINSTANCE hInstance;

    switch( msg )
    {   
    case WM_CREATE:
        {
            // LPARAM에는 CreateWindow에서 사용한 내용이 들어 있다.
            LPCREATESTRUCT p = (LPCREATESTRUCT)lParam;
            hInstance = p->hInstance;
        }
        return 0;

    case WM_LBUTTONDOWN:
        // 실행시간에 ICON을 변경하는 2가지 방법
        // 1. 클래스 자체의 ICON을 변경 - 이 클래스로 만든 모든 윈도우의 ICON 변경.
        SetClassLong( hwnd, GCL_HICON, (LONG)hIcon );
        SetClassLong( hwnd, GCL_HBRBACKGROUND, (LONG)hBrush );
        InvalidateRect( hwnd, 0, TRUE );

        // 2번째 방법 - WM_SETICON 메세지 사용 - 현재 윈도우만 변경.
        SendMessage( hwnd, WM_SETICON, 0, (LPARAM)hIcon );
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc( hwnd, msg, wParam, lParam);
}



Tags

API, 실습