Tag Archives: MFC

wave 파일 mixing 하기. (웨이브 믹싱)

용도는.. 배경음에다 목소리 합칠때 사용하는 겁니다.
검증은 좀 덜됐지만, 이런식으로 하면.. 얼마든지 응용이 가능할꺼 같네요.
그럼.. 문제 있으시면 답글 부탁드립니다.
 
 
 
// WAVE 파일을 Mixing 한다. – 배경음 + 목소리용
// [in] pFile1 : 목소리 파일
// [in] pFile2 : 배경음 파일(목소리 파일보다 커야한다.)
// [in]nPreMargineSec : 몇초 후부터 음성을 합칠것인가. (배경음만 출력되는 초기시간)
 
int WavFileMix(char *pFile1, char *pFile2, char *pFileRes, int nPreMargineSec)
{
    int len1, len2, len;
    short *in1, *in2;
    short *out;
    char pWaveHeader[44];
 
    CFile cf1, cf2, cfRes;
 
    if(!cf1.Open(pFile1, CFile::modeRead)) {
        return -1;
    }
 
    if(!cf2.Open(pFile2, CFile::modeRead)) {
        return -1;
    }
 
    DWORD dwFileSize1 = cf1.GetLength();
    len1 = dwFileSize1 – 44;
 
    DWORD dwFileSize2 = cf2.GetLength();
    len2 = dwFileSize2 – 44;
 
    int nRead2 = cf2.Read(pWaveHeader, 44);         // wave 헤더를 읽어온다.
    if(nRead2 <= 0)
        return -1;
 
    int nSamplesPerSec;
    memcpy(&nSamplesPerSec, &pWaveHeader[24], 4);   // 초당 샘플링을 읽어온다.
 
    if(len1 > len2)
        len = len1;
    else
        len = len2;
    
    in1 = (short*)malloc(sizeof(short)*len1);
    in2 = (short*)malloc(sizeof(short)*len2);
    out = (short*)malloc(sizeof(short)*len);
 
    cf1.Read(in1, len1);
    cf1.Close();
    
    cf2.Read(in2, len2);
    cf2.Close();
 
    // wave data mix
    WavMix(in1, in2, out, len1, len2, nPreMargineSec, nSamplesPerSec);
    
    //save output file  
    if(!cfRes.Open(pFileRes, CFile::modeCreate | CFile::modeWrite)) {
        free(in1);
        free(in2);
        free(out);
        return -1;
    }
 
    cfRes.Write(pWaveHeader, 44);                   // wave 헤더를 먼저 기록.
    cfRes.Write(out, len);
    cfRes.Close();
 
    free(in1);
    free(in2);
    free(out);
 
    return 0;
}
 
// Music + Voice 용도로만 사용한다. (목소리 재생시 배경음악은 볼륨을 낮춘다.)
// WAVE 데이터를 합성한다.
void WavMix(short *in1, short *in2, short *out, int nVoiceSize, int nMusicSize, int nPreMargineSec, int nSamplesPerSec)
{
    int i;
    float tmp;
    float nTemp;
 
    int nVoiceMute = nSamplesPerSec * nPreMargineSec/*초*/;
 
    for(i = 0 ;i < nMusicSize; i++)
    {
        if(i < (nVoiceSize/2)+nVoiceMute)
        {
            if( i >= nVoiceMute && i < nVoiceMute+20)
            {
                // 합쳐지는 부분의 순간 잡음을 없애기 위해.
                // 추후 Fade Out , Fade In 사용예정
                out[i] = 0;
            }
            else if(i < nVoiceMute)
            {
                // 앞에 x초는 배경음만
                out[i] = (short)in2[i];
            }
            else
            {
                // 합친다. (합친후 다시 나누기할때의 배율은 입맛에 맞게 조절한다.)
                nTemp = in1[i-nVoiceMute];
                nTemp += (float)(in2[i]*0.7);
                //tmp = (float)(nTemp / 2.0);
                tmp = (float)(nTemp / 1.7);
 
                out[i] = (short)tmp;
            }
        }
        else
        {
            // 배경음 뒷부분은 그대로..
            out[i] = (short)in2[i];
        }
    }
}

ATL/ActiveX 에서 자바스크립트로 데이터(문자열) 보내기

음.. 보통 param 으로 엑티브X로 값을 넘겨 받아서 쓰는데요

그 반대도 궁금해서 찾아봤더니 자료가 별로 없더군요.

혹시나 해서 올립니다.

1. 클래스뷰 인터페이스항목에서 메서드를 추가합니다

2. 매개 변수 형식을 VARIANT*  로 하고 특성에 out과 retval을 설정합니다. (메서드 이름과 변수 이름은 적당히…)

3. 구현부분을 다음과 같이 합니다.

STDMETHODIMP CTest::TestMethod(VARIANT* pVal)
{
    // TODO: 여기에 구현 코드를 추가합니다.
    pVal->vt=VT_BSTR;    // VARIANT 속성을 문자열로 합니다.
    pVal->bstrVal=L”테스트합니다. 이문자를 전송합니다.”;
    return S_OK;
}
 

4. 자바스크립트 추가
 

<script language=”JavaScript”>
<!–
function MyTest()
{
    var v_test;
    v_test=document.Test.TestMethod();
    alert(v_test);
}
//–>
</script>

 

<OBJECT  ID=”Test” …. >

<input type=”button” value=”문자열 받기” onClick=”MyTest();”>

 

 

 

요기서 주목할건 
 

v_test=document.Test.TestMethod();  이부분 입니다.
 

메서드 추가시 retval 항목을 선택하면 실제 리턴값은 pVal값이 됩니다. S_OK의 리턴값은 확인할수 없습니다만 ㅠ
 

신기한게 자바는 원래 포인터를 따로 쓰는게 아니라 가끔 원하지 않는 동작이 나더군요…
 

(이걸 전문용어로 설명할수 없습니다 ㅠ)
 

예를 들어 아래 처럼 하면 에러가 납니다.
 

 

retval 항목을 끄고
 

document.Test.TestMethod(v_test); 
 

라고 하면 될것 같지만 대번 에러납니다. 실력이 모자란 관계로 처음에 무척당황했습니다 -_-a
 

실제 디버그 해보면
 

STDMETHODIMP CTest::TestMethod(VARIANT* pVal)   ->   이부분에서 pVal값이 NULL이 나옵니다. ㅠ
 

이상 허접한 팁이었습니다 ㅠ
 

한분에게라도 작은 도움이 되었으면 하는 바람입니다. 🙂

System Log-Off, Suspend, Reboot, Shutdown 시키기

윈도우에서 시스템 Shutdown, Reboot, Log-Off는 ExitWindowsEx 함수로, Suspend는 SetSystemPowerState 함수로 가능합니다.
윈도우 NT를 베이스로 하는 2000, XP의 경우는 시스템을 컨트롤 하기 위해서는 권한을 변경하는 과정이 필요합니다.
 
BOOL IsWindowsNT()
{
    OSVERSIONINFO verInfo;
    verInfo.dwOSVersionInfoSize = sizeof(verInfo);
    GetVersionEx(&verInfo) ;
    switch(verInfo.dwPlatformId)
    {
        case VER_PLATFORM_WIN32_WINDOWS:
              return FALSE;
        case VER_PLATFORM_WIN32_NT:
              return TRUE;
     }
   return FALSE;
}

BOOL AdjustSystemForShutdown()
{
        if(IsWindowsNT() == FALSE)
               return FALSE ;

        HANDLE hTk;
        TOKEN_PRIVILEGES tp;

        /* Get a token for this process. */
        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTk))
                return FALSE;

        /* Get the LUID for the shutdown privilege. */
        LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tp.Privileges[0].Luid);

        tkp.PrivilegeCount = 1; /* one privilege to set */
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

        /* Get the shutdown privilege for this process. */
        return AdjustTokenPrivileges(hTk, FALSE, &tp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
}
 

이렇게 해서, 권한 변경에 성공하면 ExitWindowsEx, SetSystemPowerState 함수로 자신이 원하는 대로 시스템을 컨트롤 할 수 있습니다.
 
     // Windows 2000, XP       
     // Log Off
      ExitWindowsEx(EWX_LOGOFF|EWX_FORCEIFHUNG , SHTDN_REASON_FLAG_PLANNED );  

       // Shutdown
       ExitWindowsEx(EWX_POWEROFF|EWX_FORCEIFHUNG , SHTDN_REASON_FLAG_PLANNED ); // NT
 
       // Reboot
       ExitWindowsEx(EWX_REBOOT|EWX_FORCEIFHUNG,SHTDN_REASON_FLAG_PLANNED );

       // Suspend
       SetSystemPowerState(TRUE, TRUE ); // force suspend
 
      // Windows 95, 98, ME
      // Log Off
      ExitWindowsEx(EWX_LOGOFF|EWX_FORCE , 0 );  

       // Shutdown
       ExitWindowsEx(EWX_SHUTDOWN|EWX_FORCE, 0 ); // Windows 98, Windows ME

       // Reboot
       ExitWindowsEx(EWX_REBOOT|EWX_FORCE, 0 );

       // Suspend
       SetSystemPowerState(TRUE, TRUE ); // force suspend

GDI+ 에서 이미지 반투명 처리하기..

GDI 에선 AlphaBlend 라는 함수로 가능하기는 하는데

찍을 부분의 이미지 색상과 혼합을 해야 제대로 구현이 됩니다

계산식이야 MSDN 에도 있고 여기 Q&A 에 검색해도 있습니다.

AlphaBlend 로 하다가 계산하는거 짜증나서

GDI+ 찾아 보니까 있더군여..

MSDN 에서 발췌했습니다.

여기 검색해봐도 없길래… 갖다 붙여 넣습니다… 참고하세요..

 

 
Using a Color Matrix to Set Alpha Values in Images

The Bitmap class (which inherits from the Image class) and the ImageAttributes class provide functionality for getting and setting pixel values. You can use the ImageAttributes class to modify the alpha values for an entire image, or you can call the SetPixel method of the Bitmap class to modify individual pixel values. For more information on setting individual pixel values, see Setting the Alpha Values of Individual Pixels.

The following example draws a wide black line and then displays an opaque image that covers part of that line.

Bitmap bitmap(L”Texture1.jpg”);
Pen pen(Color(255, 0, 0, 0), 25);

// First draw a wide black line.
graphics.DrawLine(&pen, Point(10, 35), Point(200, 35));

// Now draw an image that covers part of the black line.
graphics.DrawImage(&bitmap,
   Rect(30, 0, bitmap.GetWidth(), bitmap.GetHeight()));

The following illustration shows the resulting image, which is drawn at (30, 0). Note that the wide black line doesn’t show through the image.

The ImageAtributes class has many properties that you can use to modify images during rendering. In the following example, an ImageAttributes object is used to set all the alpha values to 80 percent of what they were. This is done by initializing a color matrix and setting the alpha scaling value in the matrix to 0.8. The address of the color matrix is passed to the SetColorMatrix method of the ImageAttributes object, and the address of the ImageAttributes object is passed to the DrawImage method of a Graphics object.

 

 

// 다음 코드가 반투명 효과를 일으키게하는 소스이며.. 주석과 같이 4행4열의 0.8값을 주의깊게 보십시요

// 이 값을 바꿔주면서 이미지를 확인해 보시면 잘 알수 있을겁니다…

// 그럼.. 참고하세요..

 

 

// Create a Bitmap object and load it with the texture image.
Bitmap bitmap(L”Texture1.jpg”);
Pen pen(Color(255, 0, 0, 0), 25);

// Initialize the color matrix.
// Notice the value 0.8 in row 4, column 4.
ColorMatrix colorMatrix = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
                           0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
                           0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
                           0.0f, 0.0f, 0.0f, 0.8f, 0.0f,
                           0.0f, 0.0f, 0.0f, 0.0f, 1.0f};

// Create an ImageAttributes object and set its color matrix.
ImageAttributes imageAtt;
imageAtt.SetColorMatrix(&colorMatrix, ColorMatrixFlagsDefault,
   ColorAdjustTypeBitmap);

// First draw a wide black line.
graphics.DrawLine(&pen, Point(10, 35), Point(200, 35));

// Now draw the semitransparent bitmap image.
INT iWidth = bitmap.GetWidth();
INT iHeight = bitmap.GetHeight();
graphics.DrawImage(
   &bitmap,
   Rect(30, 0, iWidth, iHeight),  // Destination rectangle
   0,                             // Source rectangle X
   0,                             // Source rectangle Y
   iWidth,                        // Source rectangle width
   iHeight,                       // Source rectangle height
   UnitPixel,
   &imageAtt);

During rendering, the alpha values in the bitmap are converted to 80 percent of what they were. This results in an image that is blended with the background. As the following illustration shows, the bitmap image looks transparent; you can see the solid black line through it.

Where the image is over the white portion of the background, the image has been blended with the color white. Where the image crosses the black line, the image is blended with the color black.

자기자신 IP알아내기(로칼컴퓨터)

^^.
여러가지 방법이 올라와 있지만 제 컴에는 이넘 밖에 되지 않았습니다.
Test 컴파일러 : VC++6.0 , VC++.NET
 
 
#include <windows.h>
#include <winsock.h>
#include <stdio.h>
#pragma comment(lib, “ws2_32.lib”)
 
 
 
 CString CLogToNmdDlg::GetMyIp(void)
{  
    CString strHostName=””;
    CString strLocalIP=””;
 
    char  szHostName[512] = { 0, };
    DWORD dwIP    = inet_addr(“1.2.3.4”);
    PBYTE pIP     =  (PBYTE)(&dwIP);
    DWORD dwTest  = dwIP;
    printf(“%03d %03d %03d %03d
“, pIP[0], pIP[1], pIP[2], pIP[3]);
    printf(“%03d %03d %03d %03d

        , (dwTest >> 24) & 0x000000FF
        , (dwTest >> 16) & 0x000000FF
        , (dwTest >>  8) & 0x000000FF
        ,  dwTest        & 0x000000FF
        );
    if((dwTest & 0x000000FF) != pIP[4]) //printf(“당신의 시스템은 ‘호스트 바이트 오더’를 사용합니다
“);
        AfxMessageBox(“당신의 시스템은 ‘호스트 바이트 오더’를 사용합니다
“);
    else                                //printf(“당신의 시스템은 ‘네트워크 바이트 오더’를 사용합니다
“);
        AfxMessageBox(“당신의 시스템은 ‘네트워크 바이트 오더’를 사용합니다
“);
 
 
    GetMyNetworkInfo(&dwIP, szHostName, 512);
    //printf(“당신의 호스트 네임 : %s
“, szHostName);
    strHostName.Format(“당신의 호스트 네임 : %s”, szHostName);
    //printf(“당신의 아이피 주소 : %d.%d.%d.%d
“, pIP[0], pIP[1], pIP[2], pIP[3]);
    strLocalIP.Format(“당신의 아이피 주소 : %d.%d.%d.%d”, pIP[0], pIP[1], pIP[2], pIP[3]);
    //AfxMessageBox(strLocalIP);

    return strLocalIP;
}
 
BOOL CLogToNmdDlg::GetMyNetworkInfo(DWORD* pdwIP, char* szHostName, int nHostNameLength)
{
    // 인자확인
  if(!pdwIP || !szHostName || (0 >= nHostNameLength)) return false;
 
  // WSAStartup() 실행.
  WSADATA wsaData;
  WORD    wVersion = MAKEWORD(1, 1);
  if(WSAStartup(wVersion, &wsaData) == 0)
  {
    // 버전확인.
    if(wsaData.wVersion >= wVersion)
    {
      // 나의 호스트 네임 알아오기.
      if((gethostname(szHostName, nHostNameLength)) == 0)
      {
        // 나의 호스트 상세성보 알아 오기(IP알아오기)
        HOSTENT *HostEnt = gethostbyname(szHostName);
        if(HostEnt)
        {
          (*pdwIP) = (*(DWORD*)HostEnt->h_addr);
          sprintf(szHostName, HostEnt->h_addr + 4);
        }
      }
    }
 
    // WSACleanup() 실행.
    WSACleanup();
    return false;
  }
  return false;
}

ActiveX에 다이얼로그 붙이기

ActiveX Control안에 다른 ActiveX Control을 올려놓을때는 차일드 속성외에..
app에 initinstance에서 AfxEnableControlContainer();를 호출해줘야 합니다..
예..
BOOL CClientApp::InitInstance()
{
BOOL bInit = COleControlModule::InitInstance();

if (bInit)
{
// TODO: Add your own module initialization code here.
AfxEnableControlContainer();
}

return bInit;
}
수고하세요.. 직장구하고 있음..^^ 난 초보..^^

[질문 내용]***********************************************
올린이 : 이승민

ActiveX Control에 child 속성의 다이얼로그를 하나 삽입한 후..
이에 관한 클래스를 새로 생성했습니다..
그런후 ActiveX Test Container로 테스트하면 다이얼로그 까지는 나오는데…
그 다이얼로그 위에…다른 ocx를 올려놓은후..
**Ctrl클래스의 OnCreate함수에
다이얼로그의 멤버변수.Create(생성한 다이얼로그 아이디,this);
그리구 같은 클래스의 OnDraw함수에
위저드가 생성한 코드를 지우고,
다이얼로그의 멤버변수.MoveWindow(rcBounds, TRUE);
를 하면..

다이얼로그의 멤버변수.MoveWindow(rcBounds, TRUE);
를 수행하면서 에러가 납니다…

그냥 MFC위저드로해보면 잘 되는데…왜그런건지..- -‘
ocx 내에 또 다른 ocx를 삽입하려면 주의해야할 점이 있나요..
꼭 가르쳐 주세요..

모달리스 다이얼로그의 종료 버튼을 클릭했을 때 종료가 안될때…

모달리스 다이얼로그의 종료 버튼을 클릭했을 때 종료가 안될때…


요로코롬 해보슈~



WndProc(..)
{
switch()
{
   case WM_SYSCOMMAND:
   {
     if(wParam==SC_CLOSE)
     {
       EndDialog();//종료
     }
   }
}





void CESTV2WDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else if (nID==SC_CLOSE)
{
   CDialog::OnCancel();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}

ListCtrl에서 아이템 추가하기 예제

char *strTitle, *strArtist, *strTime;

{
/* Add song information to play list */
LV_ITEM lvitem;

lvitem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE ;
//  lvitem.iImage = MemoryType – 1; /* Set Image Type */
lvitem.state =  0;
lvitem.stateMask = LVIS_DROPHILITED | LVIS_SELECTED | LVIS_FOCUSED;
lvitem.lParam = 0;

int intActualItemNumber;
CString strTemp, strNumber;

if (strArtist[0]!=’

DirectShow – NULL Rendering Example

DirectShow를 이용하여 간단히 컨텐츠를 재생하는 프로그램 소스다.

이것만 이해하면 DirectShow의 절반은 이해 한 셈이다.


#include <dshow.h>

#pragma comment(lib, “strmiids.lib”)
// #pragma comment(lib, “quartz.lib”)  // usually not required if not using AMGetErrorText function

void main(void)
{
// Initialize the COM Library
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
   AfxMessageBox( “ERROR – Could not initialize COM library”);
   return;
}

// Create the filter graph manager and query for interfaces.
IGraphBuilder *pGraph = NULL;
hr = CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);

if (FAILED(hr))
{
   AfxMessageBox( “ERROR – Could not create the Filter Graph Manager.”);
   return;
}

IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
hr = pGraph->QueryInterface( IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface( IID_IMediaEvent, (void **)&pEvent);

// Build the graph.
hr = pGraph->RenderFile( L”D:RESMP3POPPet Shop BoysPet Shop Boys – I wouldn’t normally do this kind of thing.mp3″, NULL);
if (SUCCEEDED(hr))
{
   // Run the graph.
   hr = pControl->Run();
   if (SUCCEEDED(hr))
   {
     // Wait for completion.
     long evCode;
     pEvent->WaitForCompletion( INFINITE, &evCode);

     // Note: Do not use INFINITE in a real application, because it an block indefinitely.
   }
}

pControl->Release();
pEvent->Release();
pGraph->Release();

CoUninitialize();
}

Broadcast를 이용한 Application 종료

가끔 어플리케이션을에게 메시지를 보내서 통채로 죽이고 싶을때가 있다.

어플리케이션들아 우리 같이 종료하자!!!

이럴때는 윈도우 메시지를 정의해놓고,
브로드케스트 해주는 방법을 써주면 좋다.
 

보내는 곳

UINT nCloseRegMsg = ::RegisterWindowMessage(“ISCREEN_CP_APP”);
::PostMessage(HWND_BROADCAST, nCloseRegMsg, 0, 0);


받는 곳
UINT nCloseRegMsg = ::RegisterWindowMessage(“ISCREEN_CP_APP”);
if(pMsg->message == nCloseRegMsg)
{
AfxMessageBox(“I got a MSG<ISCREEN_CP_APP>!”);
}

IE Control을 사용하여 만든 어플리케이션에서 javascript로 어플리케이션에 정의된 함수 호출하는 방법

Embedded XP같은거 사용해서 커스톰 웹브라우져같은거 만들때 이런 방법을 많이 쓴다.
셋톱박스 전용 브라우져 만들때 꼭 써야하는 방식이라고나 할까…


내용 요약:
IE Control을 사용하여 개발하는 어플리케이션 내에 정의된 함수를 javascript로 window.external.[사용자 정의 함수] 로 호출하는 방법.
기본적으로는 함수는 Public으로 정의하여 구현하면 IE위에서 돌아가는 javascipt에서도 Call할수 있다.

# call방법

<script language=javascript>
window.external.사용자정의함수();
</script>


Shows how to customize the Microsoft WebBrowser control in a dialog based app to allow custom context menus, message boxes, windows, modal dialogs and C++ function calls from JavaScript to your application using window.external.

윈도우 옮기는 API – SetWindowPos

 

The SetWindowPos function changes the size, position, and Z order of a child, pop-up, or top-level window. Child, pop-up, and top-level windows are ordered according to their appearance on the screen. The topmost window receives the highest rank and is the first window in the Z order.

BOOL SetWindowPos(
  HWND hWnd,             // handle to window
  HWND hWndInsertAfter,  // placement-order handle
  int X,                 // horizontal position
  int Y,                 // vertical position
  int cx,                // width
  int cy,                // height
  UINT uFlags            // window-positioning flags
);


SAMPLE CODE ========================================

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
        HDC hdc;
        PAINTSTRUCT ps;
        char Mes[]=”왼쪽=위치 변경, 오른쪽=항상 위 옵션 변경”;
        static BOOL bTopMost=FALSE;

        switch(iMessage) {
        case WM_LBUTTONDOWN:
                SetWindowPos(hWnd, HWND_NOTOPMOST,
                        rand()%640, rand()%480, 0, 0, SWP_NOSIZE);
                return 0;
        case WM_RBUTTONDOWN:
                if (bTopMost) {
                        SetWindowPos(hWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
                } else {
                        SetWindowPos(hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
                }
                bTopMost=~bTopMost;
                return 0;
        case WM_PAINT:
                hdc=BeginPaint(hWnd, &ps);
                TextOut(hdc,10,10,Mes,lstrlen(Mes));
                EndPaint(hWnd, &ps);
                return 0;
        case WM_DESTROY:
                PostQuitMessage(0);
                return 0;
        }
        return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}

GDI+ Programming 방법

 

[중요1] Graphics 개체를 사용한다.

[중요2] 다음의 헤더선언을 꼭 해야된다

        #include <gdiplus.h>
        using namespace Gdiplus;

        #pragma comment(lib, “gdiplus.lib”) // <- 이부분은 한번반 선언하면 됨. 따라서 stdafx.cpp같은데 두면 좋음

[중요3]         
        ULONG_PTR m_gdiplusToken; // Global로 선언

        // 초기화를 위해 최소 한번 실행
            // 이부분은 GDI 개체, 즉 DC로 만들어지는 개체가 생기기 전에 생성되면 된다.
            // 예를 들어 다이얼로그 선언부 전에 선언하면 좋다.
        Gdiplus::GdiplusStartupInput gdiplusStartupInput;
        Gdiplus::GdiplusStartup( &m_gdiplusToken, &gdiplusStartupInput, NULL);  

                // Exit Instance에 실행
        GdiplusShutdown(m_gdiplusToken);


1. Graphics 개체 만드는 방법

(1) 폼 또는 컨트롤의 Paint 이벤트에서 PaintEventArgs의 일부로서 Graphics 개체에 대한 참조를 받는다.
이 방법은 대개 컨트롤을 그리는 코드를 작성할 때 Graphics 개체에 대한 참조를 가져오는 데 사용된다.

private:
   System::Void Form1_Paint(System::Object *  sender,
      System::Windows::Forms::PaintEventArgs *  pe)
   {
      // Declares the Graphics object and sets it to the Graphics object
      // supplied in the PaintEventArgs.
      Graphics * g = pe->Graphics;
      // Insert code to paint the form here.
   }



(2) 폼 또는 컨트롤의 CreateGraphics 메서드를 호출하여 해당 폼이나 컨트롤의 그리기 화면을 나타내는
Graphics 개체에 대한 참조를 가져온다. 이미 있는 폼이나 컨트롤에서 그리려는 경우에 이 방법을 사용한다.

방법1)

        Graphics * g;
        g = this->CreateGraphics();

방법2)

        // OnPaint() 이벤트에서
        CPaintDC dc(this);
        Graphics g(dc.m_hDC);


(3) Image에서 상속된 개체에서 Graphics 개체를 만든다. (가장 간단)
이 방법은 기존 이미지를 변경하려는 경우에 유용.


        Bitmap * myBitmap = new Bitmap(S”D:Documents and SettingsJoePicsmyPic.bmp”);
        Graphics * g = Graphics::FromImage(myBitmap);


예제)
        ::OnPaint()
        {
                CPaintDC dc(this);
                Graphics g(dc.m_hDC);

                CRect rect;
                GetClientRect( &rect);
                
                Image image(L”image1.jpg”);
                Rect rct( 0, 0, rect.right, rect.bottom);
                g.DrawImage( &image, rct.X, rct.Y, rct.Width, rct.Height);
        }

CFileDialog – File Open Example

CFileDialog l_SampleDlg(TRUE,NULL,NULL,OFN_OVERWRITEPROMPT,”Text Files (*.txt)|*.txt|Comma Separated Values(*.csv)|*.csv||”);
      int iRet = l_SampleDlg.DoModal();
      CString l_strFileName;
      l_strFileName = l_SampleDlg.GetPathName();

      if(iRet == IDOK)
          MessageBox(l_strFileName);
      else
          MessageBox(“No File Selected!”);

투명 윈도우 만들기

You should be able to use this demo as a skeleton application for your own project.

A standard CDialog MFC EXE application was created with the wizard and apart from the standard supplied code, the following functions were overridden.

void OnClose() Used to clean up some resources on exit.
void OnPaint() Used to paint the bimap into the region.
void OnSize(UINT nType, int cx, int cy) Used to create the region and position and resize the dialog.
void OnLButtonDown(UINT nFlags, CPoint point) To allow the dialog to be dragged by clicking anywhere.

A button was created to allow the user to close the dialog. A timer was created to demonstrate auto closing after a period of time.

The image is a normal bmp file that is loaded by the app and used to paint the dialog. TRANSPARENTCOLOR is defined in the dialog class header as bright purple (RGB(255, 0, 255), but this could be changed to any colour you like.

The dialog window is auto sized to the size of the loaded bitmap then a region created based on the transparent colour. The dialog is then positioned in the centre of the current screen. This was done as an example for those who want to use this application as a splash windows.



#define TRANSPARENTCOLOR RGB(255, 0, 255);

BITMAP  m_Bitmap;                // Struct to hold info about the bitmap
HBITMAP m_hBitmap;                // Handle of the bitmap

void CTransparentDialogDlg::OnClose()
{
        // TODO: Add your message handler code here and/or call default
        DeleteObject(m_hBitmap);        //not really need but what the heck.
        CDialog::OnClose();
}

void CTransparentDialogDlg::OnPaint()
{
        // device context for painting
        CPaintDC dc(this);
        //Create a memory DC
        HDC hMemDC = ::CreateCompatibleDC(NULL);
        //Select the bitmap in the memory dc.
        SelectObject(hMemDC, m_hBitmap);
        //Copy the memory dc into the screen dc
        ::BitBlt(dc.m_hDC, 0, 0, m_Bitmap.bmWidth, m_Bitmap.bmHeight, hMemDC, 0, 0, SRCCOPY);
        //Delete the memory DC and the bitmap
        ::DeleteDC(hMemDC);
        CDialog::OnPaint();
}

void CTransparentDialogDlg::OnSize(UINT nType, int cx, int cy)
{
        CDialog::OnSize(nType, cx, cy);
        // Load the image
        m_hBitmap = (HBITMAP)LoadImage(GetModuleHandle(NULL), “Image.bmp”, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
        if (m_hBitmap == NULL)
        {
                MessageBox(“Error loading bitmap”);
                return;
        }
        //Get information about the bitmap..
        GetObject(m_hBitmap, sizeof(m_Bitmap), &m_Bitmap);        // Get info about the bitmap
        // Put the bitmap into a memory device context
        CPaintDC dc(this);
        //get a memory dc object
        CDC dcMem;
        //create a compatible dc
        dcMem.CreateCompatibleDC(&dc);        // Select the bitmap into the in-memory DC
        //Select the bitmap into the dc
        CBitmap* pOldBitmap = dcMem.SelectObject(CBitmap::FromHandle(m_hBitmap));
        //Create a couple of region objects.
        CRgn crRgn, crRgnTmp;
        //create an empty region
        crRgn.CreateRectRgn(0, 0, 0, 0);
        //Create a region from a bitmap with transparency colour of Purple
        COLORREF crTransparent = TRANSPARENTCOLOR;        
        int iX = 0;
        for (int iY = 0; iY < m_Bitmap.bmHeight; iY++)
        {
                do
                {
                        //skip over transparent pixels at start of lines.
                        while (iX <= m_Bitmap.bmWidth && dcMem.GetPixel(iX, iY) == crTransparent)
                                iX++;
                        //remember this pixel
                        int iLeftX = iX;
                        //now find first non transparent pixel
                        while (iX <= m_Bitmap.bmWidth && dcMem.GetPixel(iX, iY) != crTransparent)
                                ++iX;
                        //create a temp region on this info
                        crRgnTmp.CreateRectRgn(iLeftX, iY, iX, iY+1);
                        //combine into main region.
                        crRgn.CombineRgn(&crRgn, &crRgnTmp, RGN_OR);
                        //delete the temp region for next pass (otherwise you’ll get an ASSERT)
                        crRgnTmp.DeleteObject();
                }while(iX < m_Bitmap.bmWidth);
                iX = 0;
        }
        //Centre it on current desktop
        SetWindowRgn(crRgn, TRUE);
        iX = (GetSystemMetrics(SM_CXSCREEN)) / 2 – (m_Bitmap.bmWidth / 2);
        iY = (GetSystemMetrics(SM_CYSCREEN)) / 2 – (m_Bitmap.bmHeight / 2);
        SetWindowPos(&wndTopMost, iX, iY, m_Bitmap.bmWidth, m_Bitmap.bmHeight, NULL);

        // Free resources.
        dcMem.SelectObject(pOldBitmap);        // Put the original bitmap back (prevents memory leaks)
        dcMem.DeleteDC();
        crRgn.DeleteObject();
}

void CTransparentDialogDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
        // TODO: Add your message handler code here and/or call default
        PostMessage( WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( point.x, point.y));
        CDialog::OnLButtonDown(nFlags, point);
}

마우스로 윈도우 드래그하여 이동시키는 비기

윈도우 드래그해서 움직이고 싶은데 어떻게 하는지 모르시는 분은 다음의 이벤트를 추가해 보시라.
 

void Cgdiplus_demoDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
        // 다음과 같이 PostMessage를 넣어주면 간단히 구현 가능
        PostMessage( WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( point.x, point.y));

        CDialog::OnLButtonDown(nFlags, point);
}

불투명 윈도우 만들기

 

* 불투명 윈도우 만들기

방금전에 책에서 본 예제로 만든겁니다.

님의 코드보다 더 자원을 먹을지는 모르겠지만 참고하세요.

윈도 2000이상에서만 된다고 하네요.

전역입니다 :

// 투명 설정을 위한 상수 정의
#define WS_EX_LAYERED       0x00080000
#define LWA_ALPHA           0x00000002

OnInitDialog에 추가 :

    // 확장 스타일에 WS_EX_LAYERED를 추가한다
    ModifyStyleEx(0, WS_EX_LAYERED);

    // user32.dll에 있는 SetLayeredWindowAttributes()의 포인터를 얻는다
    HMODULE hUserDll = ::LoadLibrary(_T(“USER32.dll”));
    typedef BOOL (WINAPI* LPSETTRANSPARENT)(HWND hWnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags);

    LPSETTRANSPARENT lpSetTransparent = NULL;
    lpSetTransparent  = (LPSETTRANSPARENT)::GetProcAddress(hUserDll, “SetLayeredWindowAttributes”);

    if(lpSetTransparent)
        // SetLayeredWindowAttributes() 함수를 호출한다.
        // 세번째 투명도는 0 ~ 255까지의 값을 설정한다
        lpSetTransparent(m_hWnd, NULL, 200, LWA_ALPHA);

    // user32.dll을 닫는다
    ::FreeLibrary(hUserDll);