728x90

탭 컨트롤을 좀 더 이쁘게 만들고 싶어서 검색하다보니 이런 자료를 찾았다.


꽤 예전에 만들어진 것 같은데... 


역시 능력자는 많은가보다. 







화면에서 보는 것과 같이 자유롭게 커스터마이징 가능하도록 Tab Control을 상속/구현하였습니다.

아직 탭/보더가 스킨 이미지로 구현된 컨트롤은 아닙니다.

현재는 GDI/GDI+ 를 이용한 직접 그리는 형태가 되겠습니다.

 

개발 환경

- Window XP : Intel X86 32bit

- Visual Studio 2005 : MFC 8.0 Unmanaged C++

 

현재 구현된 탭 스타일은 아래와 같습니다.

1. 버튼 스타일

- 가로/세로 스타일이 가능함

- 단, 세로 스타일일때는 멀티라인이어야함(이건 기본 컨트롤도 마찬가지임)

- GDI+ 이용한 그라데이션 효과를 줌

- 탭 위치 스타일이 현재 기본(Top)만 가능함. Bottom은 현재 미구현

 

2. 일반 스타일

- 가로/세로 스타일이 가능함

- 단, 세로 스타일일때는 멀티라인이어야함(이건 기본 컨트롤도 마찬가지임)

- 3D 스타일과 플랫 스타일로 변경하는 옵션

- 보더의 색을 지정하는 옵션

- 탭 위치 스타일이 현재 기본(Top)만 가능함. Bottom은 현재 미구현

 

다음은 CTabCtrlEx 클래스의 주요함수 설명입니다.

 

1. void SetColor(COLORREF crText, COLORREF crBorder, COLORREF crBackIn, COLORREF crBackOut, BOOL bRedraw=TRUE)

 : 텍스트, 배경안쪽, 배경바깥쪽, 보더 색 설정

 

2. void Set3dBorder(BOOL b3dBorder)

 : 보더 스타일 설정(TRUE=3D, FALSE=플랫)

 

3. void SetItemImage(int nItem, int nImage)

 : 해당 탭 아이템의 이미지 설정

 

4. virtual void TextOutVertical(CDC* pDC, CRect rect, CStringW sText)

 : 세로 스타일일 경우 텍스트를 한문자씩 세로로 출력

 

5. virtual void DrawMainBorder(LPDRAWITEMSTRUCT lpDrawItemStruct)

 : 메인 보더를 그림

    

6. virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)

 : 해당 탭 아이템의 텍스트를 출력

 

7. virtual void DrawItemBorder(LPDRAWITEMSTRUCT lpDrawItemStruct)

 : 해당 탭 아이템의 보더를 그림




TabCtrlEx.zip




출처 : http://yhs1981.tistory.com/entry/MFC-%EC%BB%A4%EC%8A%A4%ED%84%B0%EB%A7%88%EC%9D%B4%EC%A7%95%EC%9D%84-%EC%9C%84%ED%95%9C-Tab-Control

728x90
728x90

// 멤버 변수 추가.

HBITMAP m_bmpBackground;



// OnInitDialog() 에 추가.

m_bmpBackground = (HBITMAP)LoadImage(AfxGetApp()->m_hInstance, "이미지 경로", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);



// OnPaint() 에 추가.

CPaintDC dc(this); // device context for painting

CBitmap bmp;

BITMAP bmpInfo;

CDC memDC;


bmp.Attach(m_bmpBackground);

bmp.GetBitmap(&bmpInfo);


memDC.CreateCompatibleDC(&dc);

memDC.SelectObject(bmp);


dc.BitBlt(0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, &memDC, 0, 0, SRCCOPY);


memDC.DeleteDC();

bmp.Detach();

bmp.DeleteObject();



위와 같이 추가를 해주면 다이얼로그에 이미지가 잘 입혀질 것이다.




728x90
728x90

아래의 코드를 그냥 인쇄하고 싶은 버튼에 넣으면 된다...


    // 인쇄 코드.

    int nWidth, nHeight;

    CClientDC dc(this);  //this->pImgWnd

    CDC MemDC;

    MemDC.CreateCompatibleDC(&dc);


    CRect rect;

    GetClientRect(rect);

    nWidth = rect.Width();

    nHeight = rect.Height();


    CBitmap BMP;

    BMP.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());

    CBitmap* pOldBitmap = MemDC.SelectObject(&BMP);

    MemDC.BitBlt(0, 0, nWidth, nHeight, &dc, 0, 0, SRCCOPY);


    /*

    SECJpeg* jpg = new SECJpeg();

    jpg->CreateFromBitmap(&MemDC,&BMP);

    jpg->SaveImage("Test.jpg");

    */


    HANDLE hDib;

    LPSTR pDib;

    LPBITMAPINFO lpBitInfo;

    HANDLE hlpBitInfo;

    //CBitmap BMP;


    //BMP.LoadBitmap(IDB_BITMAP1);


    hDib = GlobalAlloc(GHND, nWidth*nHeight * 3);

    pDib = (LPSTR)GlobalLock(hDib);

    hlpBitInfo = GlobalAlloc(GHND, sizeof(BITMAPINFOHEADER) + sizeof(BITMAPINFO));

    lpBitInfo = (LPBITMAPINFO)GlobalLock(hlpBitInfo);


    //BITMAPINFO

    lpBitInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

    lpBitInfo->bmiHeader.biWidth = nWidth;

    lpBitInfo->bmiHeader.biHeight = nHeight;

    lpBitInfo->bmiHeader.biPlanes = 1;

    lpBitInfo->bmiHeader.biBitCount = 24;

    lpBitInfo->bmiHeader.biCompression = BI_RGB;

    lpBitInfo->bmiHeader.biSizeImage = nWidth * nHeight * 3;

    lpBitInfo->bmiHeader.biXPelsPerMeter = 0;

    lpBitInfo->bmiHeader.biYPelsPerMeter = 0;

    lpBitInfo->bmiHeader.biClrUsed = 0;

    lpBitInfo->bmiHeader.biClrImportant = 0;

    ////BITMAPINFO  


    HDC hdc = ::GetDC(this->m_hWnd);

    GetDIBits(hdc, (HBITMAP)BMP, 0, nHeight, pDib, lpBitInfo, DIB_RGB_COLORS);

    ::ReleaseDC(this->m_hWnd, hdc);


    static DOCINFO docinfo = { sizeof(DOCINFO), _T("IMAGE"), NULL };


    CPrintDialog dlg(FALSE);

    if (dlg.DoModal() == IDCANCEL)

        return;


    HDC hpdc = dlg.GetPrinterDC();

    int cx, cy;


    cy = GetDeviceCaps(hpdc, VERTRES);

    cx = GetDeviceCaps(hpdc, HORZRES);


    if (StartDoc(hpdc, &docinfo))

    {

        if (StartPage(hpdc))

        {

            StretchDIBits(hpdc,

                0, 0, cx, cy, 0, 0, nWidth, nHeight, pDib, lpBitInfo, DIB_RGB_COLORS, SRCCOPY);

            EndPage(hpdc);

        }

        EndDoc(hpdc);

    }

    ::RestoreDC(hpdc, -1);


출처 : http://frostguy.tistory.com/42

728x90
728x90

MFC는 기본적으로 글자 크기를 Dialog 전체적으로 바꾸게 되어 있다.


하지만 아래와 같이 작업을 해서 Item의 글자를 개별적으로 변경이 가능하다.


static CFont font;

LOGFONT logFont;


// Edit 컨트롤의 Font 정보를  LogFont에 가져온다.

GetDlgItem(IDC_EDIT_TOTAL)->GetFont()->GetLogFont(&logFont);


// Font 글자 설정.

logFont.lfWeight = 1000;

logFont.lfHeight = 30;


// logFont의 정보로 설정.

font.CreateFontIndirect(&logFont);


// Edit 박스의 Font를 설정.

GetDlgItem(IDC_EDIT_TOTAL)->SetFont(&font);




출처 : http://worhkd.tistory.com/entry/MFC-Dialog-Item%EB%93%A4%EC%9D%98-%EA%B8%80%EC%9E%90%ED%81%AC%EA%B8%B0-%EB%B3%80%EA%B2%BD

728x90
728x90

칼럼을 클릭했을 때, 오름차순 or 내림차순으로 List Control의 항목들을 정렬시키고 싶을 때에 이 코드를 추가하면 된다.


// 멤버 변수 추가.

int m_nSortColumn;

BOOL m_bAscending;



// OnLvnColumnclickListVariable 이벤트 메시지 처리기에 추가.

LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);


int column = pNMLV->iSubItem;

if (column == m_nSortedColumn)

{

    m_bAscending = !m_bAscending;

}

else

{

    m_bAscending = TRUE;

}


m_nSortedColumn = column;

int cnt = m_ListControl.GetItemCount();

CString* str = new CString[cnt];


for (int i = 0; i < cnt; ++i)

{

    str[i] = m_ListControl.GetItemText(i, column);

    m_ListControl.SetItemData(i, (DWORD)(LPCTSTR)str[i]);

}


m_ListControl.SortItems(CompareFunc, (LPARAM)m_bAscending);

delete[]str;


*pResult = 0;



// cpp에 전역 변수로 Compare함수 추가.

static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParam)

{

    BOOL Ascending = (BOOL)lParam;

    LPCTSTR s1 = (LPCTSTR)(DWORD)lParam1;

    LPCTSTR s2 = (LPCTSTR)(DWORD)lParam2;

    if (Ascending)

        return _tcscmp(s1, s2);

    else

        return -(_tcscmp(s1, s2));

    return 0;

}



출처 : http://blog.naver.com/PostView.nhn?blogId=hji0223&logNo=220661789914&categoryNo=0&parentCategoryNo=0&viewDate=&currentPage=1&postListTopCurrentPage=1&from=postView

728x90
728x90

ListCtrl 에서 여러 개의 아이템을 한번에 선택해서 삭제하기 위해서 또 코드를 입력해야한다.



어려운 코드는 아니므로 설명은 생략하겠다.

728x90
728x90

CString은 MFC에서 제공되는 정말 좋은 클래스이지만, MFC가 아닌데에서는 사용할 수 없다는 점이 너무 가슴이 아픈것 같다...


개인적으로 자주 사용하는 애들만 정리해보았다.


- CString -> DWORD



- DWORD -> CString



- 원하는 문자 삭제




- 원하는 위치의 문자 or 문자열 삭제




- 문자열 비교




- Left, Mid, Right



728x90
728x90

Dialog 기반 프로그램에서는 Enter Key, Esc Key 를 입력받게 되면 프로그램이 종료되게 된다.


뭐 ESC 키에서는 그려러니 할 수 있는데, Enter 키에서 종료가 되어버리면 원치 않는 경우일 수 있다. 

왜냐하면, Edit Box에서 입력을 하기 위해 Enter 키를 눌렀거나, Button을 키보드로 누르기 위해 Enter 키를 누를 수 있기 때문이다.


이런 것을 일명 엔터 버그라고 부른다고 한다. (책에서...)


이럴 때에는 따로 Enter, Esc 키를 눌러도 종료가 되지 않게끔 추가 작업을 해줘야 한다.


728x90

+ Recent posts