9.20(목) 실습-2

2007/10/10 20:26

1. Control 사용해보기
[ more.. | less.. ]

#define IDC_BUTTON    1
#define IDC_EDIT    2
#define IDC_LISTBOX    3

int CALLBACK foo(
ENUMLOGFONTEX *lpelfe,    // logical-font data
NEWTEXTMETRICEX *lpntme,  // physical-font data
DWORD FontType,           // type of font
LPARAM lParam             // application-defined data
)
{
    HWND hList = (HWND)lParam;
    SendMessage( hList, LB_ADDSTRING, 0, (LPARAM)lpelfe->elfLogFont.lfFaceName );
    return 1;
}

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static HWND hBtn, hEdit, hList;
    static HBRUSH brush = CreateSolidBrush( RGB(0,255,255) );
    //(HBRUSH)GetStockObject( NULL_BRUSH ); // 투명한 배경을 원할때..

    switch( msg )
    {   
    case WM_COMMAND:
        switch( LOWORD(wParam) )
        {
         case IDC_BUTTON:
            if( HIWORD(wParam) == BN_CLICKED  )
            {
                MessageBox( 0, "click", "", MB_OK );
            }
            break;
        }
        return 0;
        // EditBox가 그려지기 전에 보내는 메세지
   case WM_CTLCOLOREDIT:
        {
            HDC hdc = (HDC)wParam;
            HWND h = (HWND)lParam;

            if( h == hEdit )
            {
                SetTextColor( hdc, RGB(255, 0, 0) );
                SetBkColor( hdc, RGB(0,255,0) );
                return (LRESULT)brush;        // 리턴된 브러쉬로 배경을 채워준다.
            }
        }
        // 처리하지 않은 경우.. 반드시 디폴트로...
        // 디폴트가 기본색상을 채워준다..
        return DefWindowProc( hwnd, msg, wParam, lParam );

    case WM_CREATE:
        hBtn = CreateWindow (
 "button", "Ok", WS_CHILD | WS_VISIBLE | WS_BORDER | BS_AUTOCHECKBOX, 10, 10, 100, 100, hwnd, (HMENU)IDC_BUTTON, GetModuleHandle(0), 0 );
       
        hEdit = CreateWindow (
 "edit", "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | WS_VSCROLL | WS_HSCROLL,  210, 10, 100, 100, hwnd, (HMENU)IDC_EDIT, GetModuleHandle(0), 0 );

        // EditBox의 Margin 을 지정한다.
        SendMessage( hEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN,
            MAKELONG( 20, 30 ) );

        hList = CreateWindow( "listbox", "", WS_CHILD | WS_VISIBLE | WS_BORDER,
            410, 10, 100, 100, hwnd, (HMENU)IDC_LISTBOX, GetModuleHandle(0), 0 );

        // 역시 listbox에 항목 추가 메세지를 전달한다.
        SendMessage( hList, LB_ADDSTRING, 0, (LPARAM)"AAA" );
        SendMessage( hList, LB_ADDSTRING, 0, (LPARAM)"BBB" );
        {
            LOGFONT f;
            f.lfCharSet = DEFAULT_CHARSET;
            f.lfFaceName[0] = '\0';

            HDC hdc = GetDC(hwnd);
            EnumFontFamiliesEx( hdc, &f, (FONTENUMPROC)foo, (LPARAM)hList, 0 );

            ReleaseDC( hwnd, hdc );
        }

        // 리턴값, 클래스 이름, 캡션 내용, x좌표, ID 값을 변경하면 됩니다.
        return 0;

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


2. 사용자가 x키보드를 누를때 프로그램 종료( Messag loop 에서 하도록 함)
[ more.. | less.. ]
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

BOOL PreTranslateMessage( HWND hwnd, MSG *pMsg )
{
    if( pMsg->message == WM_KEYDOWN && pMsg->wParam == 'X' )
    {
        SendMessage( hwnd, WM_CLOSE, 0, 0 );
        return TRUE;    // 메세지를 분배 하지 않는다.
    }
    return FALSE;            // 계속 메세지를 분배한다.
}

int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
                     LPSTR      lpCmdLine, int nShowCmd )
{
    TCHAR szApp[] = _T("First");

    ATOM atom;
    WNDCLASS wc;
    HWND hwnd;
    MSG msg;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hbrBackground= (HBRUSH)GetStockObject( WHITE_BRUSH );
    wc.hCursor        = LoadCursor( 0, IDC_ARROW );
    wc.hIcon        = LoadIcon( 0, IDI_APPLICATION);
    wc.hInstance    = hInstance;
    wc.lpfnWndProc  = WndProc;
    wc.lpszClassName= szApp;
    wc.lpszMenuName = 0;
    wc.style        = 0;
    atom = RegisterClass( &wc);

    if ( atom == 0 )
    {
        MessageBox( 0, _T("Fail To RegisterClass"), _T("Error"), MB_OK);
        return 0;
    }
    hwnd = CreateWindowEx( 0, szApp, szApp, WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 0, CW_USEDEFAULT,0, 0, 0,
        hInstance, 0);
    ShowWindow( hwnd, nShowCmd);
    UpdateWindow( hwnd );

    while ( GetMessage( &msg, 0, 0, 0) )
    {                           
        //if ( msg.message == WM_KEYDOWN && msg.wParam == 'X' )
        //{
        //    SendMessage( hwnd, WM_CLOSE, 0, 0 );
        //}
        //else
        if( !PreTranslateMessage( hwnd, &msg ) )
        {
            TranslateMessage(&msg);
            DispatchMessage( &msg);
        }
    }
    return 0;
}
//-------------------------------------------------------------------------------
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static HWND hEdit;
    switch( msg )
    {
        // 사용자가 'X' 키보드를 누를때 프로그램을 종료 하는 코드를 만들어 보세요.
        // 종료하는 방법은 "SendMessage( hwnd, WM_CLOSE, 0, 0 )" 으로 하면됩니다.

        //case WM_KEYDOWN:
        //    if( wParam == 'X' ) SendMessage( hwnd, WM_CLOSE, 0, 0 );
        //    return 0;

    case WM_CREATE:
        hEdit = CreateWindow( "edit", "", WS_CHILD | WS_VISIBLE | WS_BORDER,
            10, 10, 300, 300, hwnd, (HMENU)1, GetModuleHandle(0), 0 );
        return 0;

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

3. 서브클래싱 구현( edit control 의 "ABCDEF" 를 쓰지 못하게 중간에서 가로챔 )
[ more.. | less.. ]
#define EM_SETMASK_STRING     WM_USER+999

WNDPROC EditProc;    // 원래의 메세지 처리 함수 주소를 보관할 변수

LRESULT CALLBACK foo( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    static BOOL mask[256] = { TRUE };

    switch( msg )
    {
    case EM_SETMASK_STRING:
        {
            BOOL b = (BOOL)wParam;
            char* p = (char*)lParam;

            for( int i = 0; i < 255; ++i )
            {
                mask[i] = !b;
            }
            for( int i = 0; i < strlen(p); ++i )
            {
                mask[ p[i] ] = b;
            }
        }
        return 0;
    case WM_CHAR:
        if( mask[wParam] )    // 숫자 입력
            break;
        return 0;
    }
    // WM_CHAR를 제외한 모든 메세지와 숫자인 경우는 원래의 함수로 보낸다.
    return CallWindowProc( EditProc, hwnd, msg, wParam, lParam );
    //return EditProc( hwnd, msg, wParam, lParam ); // msdn에서 UNICODE상에서 문제로 금지함..-_-.
}

LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static HWND hEdit;

    switch( msg )
    {   
    case WM_CREATE:
        hEdit = CreateWindow( "edit", "", WS_CHILD | WS_VISIBLE | WS_BORDER,
                            10, 10, 200, 200,
                            hwnd, (HMENU)1,
                            GetModuleHandle(0), 0 );

        EditProc = (WNDPROC)SetWindowLong( hEdit, GWL_WNDPROC, (LONG)foo );
        SendMessage( hEdit, EM_SETMASK_STRING, (WPARAM)FALSE, (LPARAM)"ABCDEF");
        return 0;

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

Tags

API, 실습