Child윈도우를 Popup시키는 방법


1.요약

Child윈도를 POPUP시키는 방법을 소개하겠습니다. 이것은 Toolbar가 Main Frame에서 Docking되고
Floating되는 원리와 같습니다.


2.본문

단순히 WS_CHILD속성의 윈도를 WS_POPUP속성을 주면 되지 않는다는 건 아시죠. 생성될때
 WS_CHILD속성이 정해지면 변경이 불가능합니다. 그러면 어떻게 POPUP시킬 것인가?
원리는 간단합니다. 새로운 POPUP 윈도를 하나만들고 POPUP시키고자하는 윈도의 부모를
새로 만든 POPUP 윈도로 바꿔버리는 됩니다.


3.예제

void MyWnd::PopupWindow(BOOL bPopup) 

{ 

    if (!bPopup) 

    { // Docking 

        if (m_pFloatSiteWnd) 

        { 

            m_wndChild.SetParent(this); 

            delete m_pFloatWnd; 

            m_pFloatSiteWnd = NULL; 

        } 

    } 

    else 

    { // Floating 

        if (!m_pFloatSiteWnd) 

        { 

            CRect rc; 

            m_wndChild.GetWindowRect(&rc); 

            rc.bottom += ::GetSystemMetrics(SM_CYSMCAPTION); 

            m_pFloatSiteWnd = new CWnd; 

            m_pFloatSiteWnd->CreateEx(WS_EX_TOOLWINDOW, 

                ::AfxRegisterWndClass(0, 0, (HBRUSH)COLOR_BTNFACE + 1), 

                NULL, WS_POPUP | WS_CAPTION | WS_VISIBLE, 

                rc, this, 0); 

            m_wndChild.SetParent(m_pFloatSiteWnd); 

        } 

    } 

} 











Posted by 명혀니
,




Top 윈도우들의 핸들을 알수 없을까?


1.요약

프로그램을 하다 보면, 현재 Windows System 에서 돌아가는 상위 윈도우들을 알아야 되는
경우가 있습니다. 어떻게 하면 쉬울까요?


2.본문

일반적으로 생각하기 쉬운 가장 간단한 방법은 Enumerate 입니다. 물론 이 방법이 가장 사용하기
 쉽다고 생각합니다. 하지만, 이런 방법 말고 SendMessageCallback 라는 함수를 사용하면 보다
더 쉽게 윈도우의 핸들을 알 수 있습니다. 함수의 원형은 다음과 같습니다.

BOOL SendMessageCallback( 

     HWND hWnd,                // handle to window 

     UINT Msg,                 // message 

     WPARAM wParam,            // first message parameter 

     LPARAM lParam,            // second message parameter 

     SENDASYNCPROC lpCallBack, // callback function 

     DWORD dwData              // application-defined value 

); 



VOID CALLBACK SendAsyncProc( 

    HWND hwnd,        // handle to destination window 

    UINT uMsg,        // message 

    DWORD dwData,     // application-defined value 

    LRESULT lResult   // result of message processing 

);

이중에서 우리가 살펴봐야 할것은 다섯번째 인자인, lpCallBack 입니다. CALLBACK 함수의
성격대로 윈도우가 알아서 호출해 주는 함수입니다. 그럼 언제 호출해 주는 걸까요? 메카니즘은
아래와 같습니다.

1. SendMessageCallback 로 hWnd 윈도우로 메세지를 보냅니다. 전체 상위 윈도우에게 보내기
위해서 HWND_BROADCAST(-1)을 사용합니다.
2. SendMessageCallback 를 호출한 calling window 측에서는 바로 다음 루틴을 처리할 수
있습니다.
3. hWnd 의 윈도우가 Msg 를 받게 되고, 그 메세지 루틴을 처리한다.
4. 메세지 루틴의 처리가 다 끝나면, Windows System 이 방금 메세지를 처리한 윈도우의 핸들과
처리값을 가지고, calling window의 lpCallback 함수를 호출한다.
5. calling window 측에서는 lpCallback 함수가 호출될때 적당한 작업을 한다.




Posted by 명혀니
,

for( int i = 0; i < A행렬의 행의 수; i++ ){
   
     for( int j = 0; j < B행렬의 열의 수; j++ ){

        for( int k = 0; k < B행렬의 행의 수(A행렬의 열의 수); k++ ){

            temp[i][j] += ( a[i][k] * b[k][j] );

        }

    }

}

Posted by 명혀니
,

기존의 리소스는 그대로 두고 ToolBar에 사용할 256색 이상의 Bitmap Image List를 하나 만듬니다. 그리고 나서 CToolBarCtrl의 SetImageList(), SetHotImageList(), SetDisabledImageList()를 이용하면 간단히 256이상의 ToolBar를 만들 수 있습니다. 예제를 참고하세요.

 

 

void CToolBar256::SetBitmap(UINT nIDResource, CSize ImageSize, UINT nButton, COLORREF colMask)

{

    CImageList ToolBarImageList;

    CBitmap ToolBarBitmap;

    ToolBarBitmap.LoadBitmap(nIDResource);

    ToolBarImageList.Create(ImageSize.cx, ImageSize.cy, ILC_MASK | ILC_COLORDDB, nButton, 0);

    ToolBarImageList.Add(&ToolBarBitmap, colMask);

    GetToolBarCtrl().SetImageList(&ToolBarImageList);

    ToolBarImageList.Detach();

    ToolBarBitmap.Detach();

}



void CToolBar256::SetHotBitmap(UINT nIDResource, CSize ImageSize, UINT nButton, COLORREF colMask)

{

    CImageList ToolBarImageList;

    CBitmap ToolBarBitmap;

    ToolBarBitmap.LoadBitmap(nIDResource);

    ToolBarImageList.Create(ImageSize.cx, ImageSize.cy, ILC_MASK | ILC_COLORDDB, nButton, 0);

    ToolBarImageList.Add(&ToolBarBitmap, colMask);

    GetToolBarCtrl().SetHotImageList(&ToolBarImageList);

    ToolBarImageList.Detach();

    ToolBarBitmap.Detach();

}



void CToolBar256::SetDisabledBitmap(UINT nIDResource, CSize ImageSize, UINT nButton, COLORREF colMask)

{


   CImageList ToolBarImageList; CBitmap ToolBarBitmap; ToolBarBitmap.LoadBitmap(nIDResource);


   ToolBarImageList.Create(ImageSize.cx, ImageSize.cy, ILC_MASK | ILC_COLORDDB, nButton, 0);

   ToolBarImageList.Add(&ToolBarBitmap, colMask);

   GetToolBarCtrl().SetDisabledImageList(&ToolBarImageList);

   ToolBarImageList.Detach();

   ToolBarBitmap.Detach();

}

Posted by 명혀니
,

CEdit control의 font 바꾸기


1.요약
CEdit 컨트롤의 폰트를 바꾸어 봅니다.


2.본문

Windows 95 에서 Edit control를 사용할 때는 일반적으로 font를 바꾸지 않고 그대로 사용한다. 그러나 MFC에서는 CEdit control를 사용하는 경우 CWnd::SetFont()를 이용해서 그 font를 바꿀수가 있다.

한글 Windows 95를 사용할 때는 CWnd::SetFont()에서 사용하게 될 LOGFONT의 lfCharSet 변수를 한글 Character Set code인 0x81 로 setting해 주어야 한다.

다음은 Dialog의 edit control의 font를 20 poin의 궁서체로 바꾸는 예이다.


3.예제

BOOL CMyDlg::OnInitDialog() 

{ 

    LOGFONT lf; 

    

    memset(&lf, 0, sizeof(LOGFONT)); 

    lf.lfCharSet = 0x81; // 한글 Character Set 

    lf.lfHeight = 20; // 20 point 크기 

    strcpy(lf.lfFaceName, "궁서체"); // 궁서체로 font setting 

    m_font.CreateFontIndirect(&lf); 

    

    CEdit* pCtlEdit = (CEdit*) GetDlgItem(IDC_EDIT1); // edit control의 

    // pointer를 가져옴 

    pCtlEdit->SetFont((CFont*)&m_font, TRUE); 

    

    return TRUE; 

} 

Posted by 명혀니
,

OpenCV 에서 cvNamedWindow 로 만들어진 윈도우는 cvGetWindowHandle 로 핸들을 얻어올 수 있는데 이는 OpenCV를 출력하는 다이얼로그 윈도우의 클라이언트 핸들(HWND) 입니다. 다이얼로그 프레임을 갖고 오려면 얻어진 핸들에서 GetParent 를 해서 갖고 오면 되고요..


열리진 윈도우 창의 이름을 알면 ::FindWindow(NULL, _T("창이름")) 로 CWnd 를 찾아 올 수 있습니다.



추가로... 채널을 분리하려면


cvSplit 나 cvCvtPixToPlane 를 사용하면 됩니다. 두 함수는 동일한 함수 이고요...

cvSplit(SrcImage, ch1, ch2, ch3, ch4);


SrcImage 가  RGB채널 영상의 경우  빨간색 채널만 얻어오려면...


IplImage* pIplRed = cvCreateImage(cvGetSize(SrcImage), IPL_DEPTH_8U, 1);
cvSplit(SrcImage, NULL, NULL, pIplRed, NULL); 
Posted by 명혀니
,
수행 시간이 긴 프로그램을 실행시키다 보면 화면 보호기가 종종 방해가 됩니다. 윈도우의 화면 보호기를 매번 켜고 끄는 대신 프로그램이 실행 중인 동안만 화면 보호기가 동작하지 않도록 하기 위해서는 프로그램에서 화면 보호기가 동작하는 메시지를 처리해주면 됩니다.

  화면 보호기가 동작할 때 발생하는 메시지는 SC_SCREENSAVE입니다. 실행 중인 프로그램 윈도우가 활성화된 상태에서는 메시지가 먼저 활성화된 윈도우로 전달되므로, PreTranslateMessage에서 이를 처리해주면 됩니다. 이 때 true 값을 return해 주면 더 이상 메시지가 전파되지 않으므로 화면 보호기가 작동하지 않습니다.

    BOOL CTestDlg::PreTranslateMessage(MSG* pMsg)
    {
            // TODO: Add your specialized code here and/or call the base class
            if(pMsg->wParam ==
    SC_SCREENSAVE && pMsg->message == WM_SYSCOMMAN
    D)
                    return TRUE;
           
            return CDialog::PreTranslateMessage(pMsg);
    }

Posted by 명혀니
,
CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd();
 CChildFrame *pChild = (CChildFrame *)pFrame->GetActiveFrame();
 COpenMFCDoc *pDoc = (COpenMFCDoc *)pChild->GetActiveDocument();

다음과 같은식으로 얻어와야한다


sdi 와 착각하지말자 !!

Posted by 명혀니
,
// Least Square Method (최소 자승법)

#include <stdio.h>
#include <math.h>

int  lstsq(double x[], double y[], int n, int number, double c[]);

const int n = 1; // 구하려는 함수의 차수
const int number = 10; // 데이터의 갯수

double x[number] = { 4.0, 4.2, 4.5, 4.7, 5.1, 5.5, 5.9, 6.3, 6.8, 7.1 },
       y[number] = { 102.56, 113.18, 130.11, 142.05, 167.53, 195.14,
224.87, 256.73,299.50,326.72}; double p; void main() { double c[number], error=0.0; int chkerr, i; printf(" < Least Squre Method > \n\n"); chkerr = lstsq(x, y, n, number, c); // 결과 출력 for(i=0; i<=n; i++) printf("a%d = %10.8f\n",i, c[i]); if(chkerr==0) printf("\nNo Error"); else printf("\nError"); } // 0 출력-> 에러없음, 999 출력-> 계산에러 int lstsq(double x[], double y[], int n, int number, double c[]) { int i, j, k, l; double w1, w2, w3, pivot, aik, a[21][22], w[42]; if(n >= number || n < 1 || n > 20) return(999); for(i = 0; i < n*2; i++) { w1 = 0.0; for(j = 0; j < number; j++) { w2 = w3 = x[j]; for(k = 0; k < i; k++) w2 *= w3; w1 += w2; } w[i] = w1; } // matrix 입력 for(i = 0; i < n+1; i++) { for(j = 0; j < n+1; j++) { l = i + j - 1; a[i][j] = w[l]; } } a[0][0] = number; w1 = 0.0; for(i = 0; i < number; i++) w1 += y[i]; a[0][n+1] = w1; // sigma(Yi Xi) 계산해서 대입 for(i = 0; i < n; i++) { w1 = 0.0; for(j = 0; j < number; j++) { w2 = w3 = x[j]; for(k = 0; k < i; k++) w2 *= w3; w1 += y[j] * w2; } a[i+1][n+1] = w1; } // matrix 계산 for(k = 0; k < n+1; k++) { pivot = a[k][k]; for(j = k; j < n+2; j++) a[k][j] /= pivot; for(i = 0; i < n+1; i++) { if(i != k) { aik = a[i][k]; for(j = k; j < n+2; j++) a[i][j] -= aik * a[k][j]; } } } // 다항식의 계수를 최종적으로 전달 (pass by reference) for(i = 0; i < n+1; i++) c[i] = a[i][n+1]; return(0); }
Posted by 명혀니
,

//트리컨트럴이 그려질 부모 윈도우 즉 view클래스 헤더 파일에


//뷰클래스 안에다

CTreeCtrl m_treeCtrl; //변수를 선언하고


public:

    afx_msg void OnTvnItemexpandedTree1(NMHDR *pNMHDR, LRESULT *pResult);//요거는 트리가 접히거나 펴질때 발생합니다.




//view 클래스 cpp파일의 클래스 밖에 맨 윗부분이나 맨 아래 요렇게 콜백함수(시스템이 호출하는함수)를 만듭니다.


WNDPROC g_wndProc;

bool SetBkImage(HDC hdc,const TCHAR *szImage,CRect rect,int iMode);//이미지를 그려주는 전역함수

bool LoadGraphicFile(LPCWSTR szFileName,HBITMAP &hBmp,BITMAP *bmp);//그래픽(bmp,jpg,gif,png)파일 로드전역 함수


LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{  

    switch(iMsg)

    {

    case WM_ERASEBKGND://배경을 다시그릴때 호출됩니다.

        {

        CRect rc;

        GetClientRect(hwnd,&rc);

        //배경그림을 설정하는 함수 호출(전역함수)

        if(SetBkImage((HDC)wParam,_T("love1.gif"),rc,1)) return 1;//요 함수는 클래스 밖에 있는 함수입니다. 따라서 맨 밑에

       //view 클래스 밖에다가 만듭니다.

        }

    case WM_VSCROLL | WM_HSCROLL://스크럴 바를 움직일때 호출됩니다.

        {

        CRect rc;

        GetClientRect(hwnd,&rc);//윈도우중 사용자영역의 사각좌표를 얻는다.

        if(LOWORD(wParam)==SB_THUMBTRACK)//스크럴 바를 끌고 있을때

            ::InvalidateRect(hwnd,rc,1);//배경을 지우고 다시 그린다.

        break;

        }

    }

    return CallWindowProc (g_wndProc, hwnd, iMsg, wParam, lParam) ;

}



//그리고 view 클래스 안쪽에다가  요렇게 트리컨트럴을 대화상자의 트리컨트럴ID와 연결합니다.

void CexamView::DoDataExchange(CDataExchange* pDX)

{

                    CFormView::DoDataExchange(pDX);

DDX_Control(pDX, IDC_TREE1, m_treeCtrl);

}


//다음  view 만든후 처음 호출되는 대화상자의 모든 컨트럴을 로드한 후 호출되는 메시지에

//요렇게 m_treeCtrl의 핸들을 이용하여 컨트럴 자체의 메시지를 가로챕니다.


void CexamView::OnInitialUpdate()

{

    CFormView::OnInitialUpdate();


g_wndProc=(WNDPROC)SetWindowLong(m_treeCtrl.m_hWnd,GWL_WNDPROC,(LONG)WndProc);

//g_wndProc는 전역 WNDPROC이어야 합니다. 요새는 SetWindowLongPtr이거를 사용하라고 마소에서 권고합니다.^^


}


//그리고 트리컨트럴이 부모윈도우(view)에 보내는 메시지중 TVN_ITEMEXPANDING 이거를 받습니다.

//트리노드가 펼치거나 접혀질때 발생합니다.

//요렇게 그때마다 트리컨트럴을 다시 그립니다.


void CexamView::OnTvnItemexpandedTree1(NMHDR *pNMHDR, LRESULT *pResult)

{

    LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);

    // TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.

    CRect rc;

    m_treeCtrl.GetClientRect(&rc);

    m_treeCtrl.Invalidate();

    *pResult = 0;

}


//마지막으로 배경을 그려주는 전역 함수를 맨 밑에다 클래스 밖에 만들어 줍니다.


bool SetBkImage(HDC hdc,const TCHAR *szImage,CRect rect,int iMode)

{

    HDC memDC;

    HBITMAP hbmp=NULL,hbmpPrev;

    BITMAP bmp;

    bool bReturn=true;//반환 값

   

    //그래픽파일 로드

    if(!LoadGraphicFile(szImage,hbmp,&bmp)) return false;


    //메모리 DC 만듬    

    memDC=CreateCompatibleDC(hdc);

    //로드된 비트맵을 DC에 선택

    hbmpPrev=(HBITMAP)SelectObject(memDC,hbmp);

    //배경채우기 선택

    if(iMode==0)//늘이기

    {

        SetStretchBltMode(hdc,COLORONCOLOR);

        StretchBlt(hdc,0,0,rect.Width(),rect.Height(),memDC,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);

    }

    else if(iMode==1)//바둑판식

    {

              //바둑판식 효과

         for (int y=0; y < rect.Height(); y += bmp.bmHeight)

         { // for each row:

             for (int x=0; x < rect.Width(); x += bmp.bmWidth)

             { // for each column:

               BitBlt(hdc,x, y,bmp.bmWidth ,bmp.bmHeight ,memDC, 0, 0, SRCCOPY); // copy

               

             }

          }

    }

    else if(iMode==2)//가운데

    {

        LOGBRUSH lb;//브러쉬 구조체

        HBRUSH hbrush,hbrushPrev;//브러쉬 핸들

        //브러쉬 스타일과 색상

        lb.lbStyle=BS_SOLID   ;lb.lbColor=GetBkColor(hdc);

        //브러쉬를 만든다.

        hbrush=CreateBrushIndirect(&lb);

        //DC에 브러쉬를 선택

        hbrushPrev=(HBRUSH)SelectObject(hdc,hbrush);

        Rectangle(hdc,0,0,rect.right,rect.bottom);//사각형을 그린다.

        SelectObject(hdc,hbrushPrev);//브러쉬 환원

        DeleteObject(hbrush);//브러쉬 삭제

        //메모리 DC에 있는 그림을 목적 DC로 전송

        //좌표를 계산한다

        //그림의 넓이가 DC의 넓이 보다 크면 X좌표는 0 그렇지 않으면

        //DC의 넓이를 반으로 나눈 값에서 그림의 넓이를 반으로 나눈 값을 뺀다.

        //Y좌표도 마찬가지 방법으로 계산한다.

        rect.Width()/2>=bmp.bmWidth?rect.left=rect.Width()/2-bmp.bmWidth/2:rect.left=0;

        rect.Height()/2>=bmp.bmHeight?rect.top=rect.Height()/2-bmp.bmHeight/2:rect.top=0;

        BitBlt(hdc,rect.left,rect.top,rect.Width(),rect.Height(),memDC,0,0,SRCCOPY);


    }

    else //모드 에라;;

    {   AfxMessageBox(_T("인식할수 없는 Fill Mode 입니다."));bReturn=false;}

   

    SelectObject(memDC,hbmpPrev);DeleteObject(hbmp);

    DeleteDC(memDC);

    return bReturn;

}


bool LoadGraphicFile(LPCWSTR szFileName,HBITMAP &hBmp,BITMAP *bmp)

{

     HRESULT hr;

     HANDLE hFile = CreateFileW(szFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);

    if(INVALID_HANDLE_VALUE == hFile)

    {

        AfxMessageBox(_T("Graphic File Open Error"));

        return false;

    }

    // 파일의 사이즈를 얻는다.

    DWORD dwFileSize = GetFileSize(hFile, NULL);

    if(-1 == dwFileSize)

    {

        AfxMessageBox(_T("Graphic File Read Error"));

        return false;

    }

       

    LPVOID pvData = NULL;

    // 파일의 크기만큼 동적할당(alloc memory based on file size)

    HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE,dwFileSize);

    if(NULL == hGlobal) return false;

    pvData = GlobalLock(hGlobal);

    if(NULL == pvData) return false;

    DWORD dwBytesRead = 0;

    // 파일을 읽고 할당된 전역공간에 저장(read file and store in global memory)

    BOOL bRead = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL);

    if(FALSE == bRead) return false;

    GlobalUnlock(hGlobal);

    CloseHandle(hFile);

    LPSTREAM pstm = NULL;

    // create IStream* from global memory

    hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pstm);

    if(S_OK != hr || pstm == NULL) return false;

     // Create IPicture from image file


    LPPICTURE pPicture;

    hr = ::OleLoadPicture(pstm,dwFileSize, FALSE, IID_IPicture, (LPVOID *)&pPicture);

    if(S_OK != hr || pPicture == NULL)

    {

        AfxMessageBox(_T("Graphic File Load Error"));

        return false;

    }

    pstm->Release();

    GlobalFree(hGlobal);

    OLE_HANDLE picHandle;

    pPicture->get_Handle(&picHandle);


    hBmp=(HBITMAP)picHandle;

    if(NULL!=bmp)

        GetObject(hBmp,sizeof(BITMAP),bmp);

    return true;


Posted by 명혀니
,