// 주어진 크기만큼 공백을 삽입한다.

static void Blank(int n)

{

int k = 16-n;

k = k*3 + (n<7?1:0);

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

printf(" ");

}



// 바이너리 데이터를 정규 포멧으로 출력한다.

void PrintBinary(BYTE* buffer, int length)

{

int row = length/16;

int col = length%16;

int i, j;

int prev = 0;

for(i=0; i<=row; i++)

{

int end = 16;

if(i == row)

end = col;

else

end = 16;



printf("%06X  ", i*16);



for(j=0; j<end; j++)

{

printf("%02X ", buffer[i*16+j]);

if(j==7)

printf(" ");

}

Blank(end);

printf("    ");

for(j=0; j<end; j++)

{

char ch = buffer[i*16+j];

char ch1 = buffer[i*16+j+1];

if(isprint(ch))

printf("%c", ch);

else

{

if((ch >> 7) & 0x01 == 1 && (ch1 >> 7) & 0x01 == 0 && prev == 0)

{

printf("%c", ch);

prev = 1;

}

else

{

if(prev == 1)

{

printf("%c", ch);

prev = 0;

}

else

printf(".");

}

}



if(j==7)

printf(" ");

}



printf("\n");

}

}



// 바이트 데이터를 이진수 문자열로 출력한다.

void PrintByte(BYTE ch)

{

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

printf("%c", (ch>>(7-i)&0x01)?'1':'0');

현재 이넘은 윈XP만 지원한덴다.

typedef HRESULT (WINAPI MF)(HWND hwndParent, LPCWSTR pszPath);

void CAaaDlg::OnButton1()
{
HMODULE hm = ::LoadLibrary("ntshrui.dll");
if(!hm)
return;

MF* proc = (MF*)GetProcAddress(hm, "ShowShareFolderUIW");

wchar_t str[] = L"C:\\Windows\\";

if(proc)
{
HRESULT f = proc(m_hWnd, str);
int a = 0;
}

::FreeLibrary(hm);
}
올리기올려짐: 토 8월 12, 2006 1:22 am    주제: [팁] 풀 스크린 (SDI/ MDI) 인용과 함께 답변 글 편집/삭제 글 삭제 글 올린이의 IP 주소 보기

메인 프레임 헤더...

BOOL m_IsFullScreen;
WINDOWPLACEMENT m_wpPrev;
void SetFullScreen();


메인 프레임 소스...

void CMainFrame::SetFullScreen()
{
WINDOWPLACEMENT wpNew;
CRect rectDesktop;

if (!m_IsFullScreen)
{
// 툴바와 상태바를 감춘다.
m_wndStatusBar.ShowWindow(SW_HIDE);
m_wndToolBar.ShowWindow(SW_HIDE);

// 현재 윈도우의 위치를 얻어온다.
GetWindowPlacement (&m_wpPrev);
m_wpPrev.length = sizeof m_wpPrev;

::GetWindowRect ( ::GetDesktopWindow(), &rectDesktop );
::AdjustWindowRectEx(&rectDesktop, GetStyle(), TRUE, GetExStyle());

wpNew = m_wpPrev;
wpNew.showCmd = SW_SHOWNORMAL;
wpNew.rcNormalPosition = rectDesktop;
m_IsFullScreen=TRUE;
}
else
{
m_IsFullScreen=FALSE;
// 툴바와 상태바를 보여준다.
m_wndStatusBar.ShowWindow(SW_SHOWNORMAL);
m_wndToolBar.ShowWindow(SW_SHOWNORMAL);
wpNew = m_wpPrev;
}

SetWindowPlacement ( &wpNew );
}

void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
CRect rectDesktop;
::GetWindowRect ( ::GetDesktopWindow(), &rectDesktop );
::AdjustWindowRectEx(&rectDesktop, GetStyle(), TRUE, GetExStyle());
// 윈도우의 최대 사이즈를 얻어온다.
if (m_IsFullScreen)
{
lpMMI->ptMaxSize.y = rectDesktop.Height();
lpMMI->ptMaxTrackSize.y = lpMMI->ptMaxSize.y;
lpMMI->ptMaxSize.x = rectDesktop.Width();
lpMMI->ptMaxTrackSize.x = lpMMI->ptMaxSize.x;
}
CFrameWnd::OnGetMinMaxInfo(lpMMI);
}

BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
{
//ALT + Enter를 누르면 풀 스크린이당 ^^
if(pMsg->message == WM_SYSKEYDOWN && pMsg->lParam == 0x201C0001)
SetFullScreen();
return CFrameWnd::PreTranslateMessage(pMsg);
}


MDI 일경우는...
차일드 프레임 소스...
void CChildFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
if(pFrame)
{
CRect rectDesktop;
::GetWindowRect ( ::GetDesktopWindow(), &rectDesktop );
::AdjustWindowRectEx(&rectDesktop, GetStyle(), TRUE, GetExStyle());
// 윈도우의 최대 사이즈를 얻어온다.
if (pFrame->m_IsFullScreen)
{
lpMMI->ptMaxSize.y = rectDesktop.Height();
lpMMI->ptMaxTrackSize.y = lpMMI->ptMaxSize.y;
lpMMI->ptMaxSize.x = rectDesktop.Width();
lpMMI->ptMaxTrackSize.x = lpMMI->ptMaxSize.x;
}
}

CMDIChildWnd::OnGetMinMaxInfo(lpMMI);
}
HINSTANCE FindExecutableEx(... 인자는 동일하다 ...)
{
TCHAR drive[_MAX_DRIVE];
TCHAR dir[_MAX_DIR];
TCHAR dir1[_MAX_DIR];
TCHAR file[_MAX_FILE];
TCHAR ext[_MAX_EXT];

HINSTANCE hi = FindExecutable(file, dir, result);
result[lstrlen(result)] = 32;

_splitpath(result, deive, dir, file, ext);

LPTSTR p = strchr(dir, ':');
if(p != NULL)
{
--p;
dir[p-dir] = 0;
_splitpath(dir, NULL, dir1, file, ext);
p = strchr(ext, 32);
ext[p-ext] = 0;
_makepath(result, drive, dir1, file, ext);
}
return hi;
}
약속한데로... 자세한 설명을 해 드리죠.

1. 초기화 과정입니다.

BOOL CCaptureDlg::OnInitDialog()
{
// VC++ 에서 지원한는 Smart Poniter 라는 것으로 구현 했습니다.
// 전병선씨가 지은 ATL/COM 프로그램밍 책에 보시면 자세히 설명하는데
// 사 보셔도 좋고요. 앞으로 ATL 을 공부하시는데 도움이 될겁니다.
// 연락 주시면 가지고 있는 COM 관련 추천 책들도 알려 드리죠.


// InitInstance() 에 AfxOleInit() 가 추가 되어 있는지 확인한다.
m_pZlib = IZlibAtlPtr(__uuidof(ZlibAtl));

// 만일 ZlibUtil 이 이벤트를 받고 싶을때 다음의 리마크를 없애세요.
// 이벤트 처리는 ZlibUtil 가 같이 샘플로 제공된 createzipstg 에 이벤트
// 처리를 윈한 코드들이 들어 갔으니까 참고 하세요.
// 만일 안 쓰시겠다면 다음 코드들은 지워도 됩니다.

// m_pEvent = new CZlibEvent(this);
// BOOL bAdvised = AfxConnectionAdvise(m_pZlib, DIID__IZlibAtlEvents,
// m_pEvent->GetInterface(&IID_IUnknown),
// TRUE, &m_dwCookie);
}


2. 캡쳐 하기입니다.

void CCaptureDlg::OnCapture()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);

// CDib 는 밑에 김서영님의 올린 것을 Wrap 한 함수입니다.
// 참고해서 읽어 보세요.

CDib dib;
CRect rect(atoi(m_szX),atoi(m_szY),atoi(m_szX)+atoi(m_szW),atoi(m_szY)+atoi(m_szH));
CSize destSize(atoi(m_szW),atoi(m_szH));

if(m_hDIB) {
GlobalFree(m_hDIB); // 전에 가지고 있던 메모리를 해제함.
}

UINT size;
dib.WriteWindowToDIB(rect, destSize, m_hDIB, size);

HBITMAP hBitmap;

// BitmapFromDib 는 MS 사 ShowDib(dib.c) 라는 샘플에 있던 것으로
// Bitmap Image 가지고 할수 있는 Wrap 함수들입니다.
// 쓸만한것이 상당히 많으니까 한번씩 이름만이라도 보시면 도움이
// 되겠군요.
hBitmap = BitmapFromDib (m_hDIB, NULL);

// m_Picture.m_pPict 는 CPitureHodler 라는 클래스로 ActiveX
// 의 Picture Proprety 를 Wrap 클래스 입니다.
// 멤버 함수들은 MSDN 을 참고 하시고...
// 여기서는 그냥 BITMAP Handle 을 통해서 Picture 을 생성하면
// 되겠습니다.
m_Picture.m_pPict.CreateFromBitmap(hBitmap, NULL);

// 화면 재 갱신을 하시면 m_Picture 의 OnPaint() 에서
// 화면의 크기를 계산하고 m_pPict 의 Render 를 Call 해서
// 화면에 직접 그림니다.

// 게으른 관계로 ActiveX Picture Wrap Class 를 써서
// 화면 출력을 구현했습니다.
m_Picture.Invalidate();
}


3. 압축하기 인데 상당히 소스가 길어 보이죠...
파라미터로 화일명과 DIB 에 대한 핸들을 주면 됩니다.

BOOL CCaptureDlg::WriteDIBToZip( LPSTR szFile, HANDLE hdib)
{
BITMAPFILEHEADER hdr;
LPBITMAPINFOHEADER lpbi;

if (!hdib)
return FALSE;

lpbi = (LPBITMAPINFOHEADER)GlobalLock (hdib);

/* Fill in the fields of the file header */
// BITMPAP FILE 에 대한 설명이군요.
hdr.bfType = BFT_BITMAP;
hdr.bfSize = GlobalSize (hdib) + SIZEOF_BITMAPFILEHEADER_PACKED;
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits = (DWORD) (SIZEOF_BITMAPFILEHEADER_PACKED + lpbi->biSize +
PaletteSize(lpbi));

try {
/* Write the file header */

IStreamPtr pstrmInMem;
ULONG cbWritten = 0;
ULONG cbTotal = 0;
HRESULT hr = S_OK;

// 화일을 대신할 Stream 을 만든다.
// 하나의 화일로 되어 있으면 그것을 바로 메모리로 옮기고 압축하면
// 좋겠지만 그러하지 않으니까... 일단 만듭니다.
hr = CreateStreamOnHGlobal(NULL, TRUE, &pstrmInMem);
_com_util::CheckError(hr);

#ifdef FIXDWORDALIGNMENT
hr = pstrmInMem->Write(hdr, (UINT)(SIZEOF_BITMAPFILEHEADER_PACKED), &cbWritten);
_com_util::CheckError(hr);

cbTotal += cbWritten;
#else
/* write bfType*/
hr = pstrmInMem->Write(&hdr.bfType, (UINT)sizeof (WORD), &cbWritten);
_com_util::CheckError(hr);
cbTotal += cbWritten;

/* now pass over extra word, and only write next 3 DWORDS!*/
hr = pstrmInMem->Write(&hdr.bfSize, sizeof(DWORD) * 3, &cbWritten);
_com_util::CheckError(hr);
cbTotal += cbWritten;
#endif

/* this struct already DWORD aligned!*/
/* Write the DIB header and the bits */
hr = pstrmInMem->Write(lpbi, GlobalSize (hdib), &cbWritten);
_com_util::CheckError(hr);
cbTotal += cbWritten;

// 이제 pstrmInMem 는 Bitmap 화일과 같습니다.

// pstrmInMem 을 압축하겠습니다.
#ifdef USE_MEMORY // 메모리를 사용할 경우.

// SafeArray 는 컴퍼넌트간 메모리를 통한 복사를 위한 함수입니다.
// 1. Create 하기(Create)
// 2. 메모리를 Lock 하기(AccessData)
// 메모리를 데이타를 써넣고
// 3. 메모리를 UnLock 하기(UnaccessData)
// 4. Create 된것을 지우기 (Destroy)
_variant_t var;
PCHAR pBuf;
PBYTE pArr;
DWORD dwLen = cbTotal; // 크기 지정함
SAFEARRAY FAR* psa;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = dwLen;
psa = SafeArrayCreate(VT_UI1, 1, rgsabound); //1. 동적으로 메모리 생성
if(psa == NULL) {
_com_issue_error(S_OK);
}

hr = SafeArrayAccessData(psa, (PVOID *)&pBuf); // 2. Lock 하기
_com_util::CheckError(hr);

memset(pBuf, 0, dwLen);

HGLOBAL global;
GetHGlobalFromStream(pstrmInMem, &global);

LPVOID pVoid = GlobalLock(global);
CopyMemory(pBuf, pVoid, dwLen); // 데이타 쓰기
GlobalUnlock(global);

hr = SafeArrayUnaccessData(psa); // 3. Unlock 하기
_com_util::CheckError(hr);

var.vt = VT_ARRAY|VT_UI1|VT_BYREF; // VARAINT (MSDN 참조) 에 ARRAY 를 포인터로
var.parray = psa; // 넘긴다고 지정함.
m_pZlib->PutMode(MEM_TO_ZMEM); // ZLibUtil 에게 메모리(SafeArray) 사용을
// 알림

m_pZlib->PutInMemory(var); // variant 데이타 넘김(이미 데이타는 저장됨)

hr = m_pZlib->Compress(); // ZLibUtil 에게 압축을 지시함
_com_util::CheckError(hr);

SafeArrayDestroy(psa); // 4. Create 된 데이타 지우기
_variant_t outvar; // 이미 압축된 결과 데이타는 컴퍼넌트 안에
outvar = m_pZlib->GetOutMemory(); // 들어 있다.
// ZLibUtil 에게 데이타 요구함(Variant)
LONG lLbound, lUbound; // Vairant(outvar) 에 이미 데이타가들어와 있음
hr = SafeArrayGetLBound(outvar.parray, 1, &lLbound); // 크기를 알아냄(최하)
_com_util::CheckError(hr);

hr = SafeArrayGetUBound(outvar.parray, 1, &lUbound); // 크기를 알아냄(최상)
_com_util::CheckError(hr);
hr = SafeArrayAccessData(outvar.parray, (PVOID *)&pArr); // 실제 데이타 위치
_com_util::CheckError(hr); // 메모리 포인터

ULONG StoreLen; // 받을때 SafeArray 쓰는 것도 같습니다.
// 이미 컴퍼넌트가 Create 했으므로 2,3 과정만 하면 됩니다.
// 4 과정은 컴퍼넌트가 수행할 겁니다.
StoreLen = lLbound + lUbound+1; // 실제 받을 데이타 크기.

CFile file;
if(file.Open(szFile, CFile::modeCreate | CFile::modeWrite) ) {
file.WriteHuge(pArr, StoreLen);
file.Close();
}
else {
hr = SafeArrayUnaccessData(outvar.parray); // 3과정
_com_util::CheckError(hr);

_com_issue_error(S_OK);
}

hr = SafeArrayUnaccessData(outvar.parray);
_com_util::CheckError(hr);


#else // Stream 으로 사용할 경우
IStreamPtr pstrmOutMem;

hr = CreateStreamOnHGlobal(NULL, TRUE, &pstrmOutMem); // OutStream
_com_util::CheckError(hr); // 메모리에 화일을 대신할 메모리 Stream 을 만든다.

m_pZlib->PutMode(STREAM_TO_ZSTREAM); // Stream 압축을 지정함

LARGE_INTEGER li;
li.LowPart = li.HighPart = 0;

pstrmInMem->Seek(li, STREAM_SEEK_SET, NULL); // 이미 써넣으면서 뒤로 위치했으므로
// 앞으로 되돌림.
m_pZlib->PutInStream(pstrmInMem); // In 지정
m_pZlib->PutOutStream(pstrmOutMem); // Out 지정

m_pZlib->Compress(); // 압축
pstrmOutMem->Seek(li, STREAM_SEEK_SET, NULL);// 컴퍼넌트가 보낸데이타를 맨앞에서
// 부터 읽을 준비를 함.

CFile file;
if(file.Open(szFile, CFile::modeCreate | CFile::modeWrite) ) {
while(TRUE) {
char buf[8192];
ULONG cbRead = 0;
pstrmOutMem->Read(buf, 8192, &cbRead); // 8192로 계속 읽어 옵니다.

if(cbRead == 0)
break;

file.Write(buf, cbRead);
}
file.Close();
}
else {
_com_issue_error(S_OK);
}

#endif
}
catch (_com_error e){
HRESULT hr = e.Error();
if(hr != S_OK)
ShowMessage(e);

GlobalUnlock (hdib); // Lock 된 데이타 UnLock 함
return FALSE;
}

GlobalUnlock (hdib);
return TRUE;
}

4. 읽어 오기

HANDLE CCaptureDlg::LoadDIBFromZip( LPSTR szFile)
{
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
DWORD dwLen = 0;
DWORD dwBits;
HANDLE hdib = NULL;
HANDLE h;
ULONG cbRead = 0;

/* Open the file and read the DIB information */
// 이미 메모리에 대한 설명은 저장하기에서 했으므로
// 간단히 Stream 으로 가지고 작업 하기로 하겠습니다.
try {
IStreamPtr pstrmInMem;
IStreamPtr pstrmOutMem;
HRESULT hr = S_OK;

hr = CreateStreamOnHGlobal(NULL, TRUE, &pstrmInMem);
_com_util::CheckError(hr);

hr = CreateStreamOnHGlobal(NULL, TRUE, &pstrmOutMem);
_com_util::CheckError(hr);

CFile file;

if(file.Open(szFile, CFile::modeRead)) {
while(TRUE) {
char buf[8192];
ULONG cbWritten = 0;
UINT cbRead = file.Read(buf, 8192);

if(cbRead == 0)
break;

pstrmInMem->Write(buf, cbRead, &cbWritten);
}

m_pZlib->PutMode(ZSTREAM_TO_STREAM); // 압축된 스트림에서 스트림으로

LARGE_INTEGER li;
li.LowPart = li.HighPart = 0;

pstrmInMem->Seek(li, STREAM_SEEK_SET, NULL); // 읽어 오면서 뒤로간
// InStream 을 되 돌림
m_pZlib->PutInStream(pstrmInMem); // InStream 지정
m_pZlib->PutOutStream(pstrmOutMem); // OutStream 지정

m_pZlib->Decompress(); // 풀기
pstrmOutMem->Seek(li, STREAM_SEEK_SET, NULL);// 컴퍼넌트에서 온 데이타를
// 앞에서 쓸수 있도록 되돌림
}
else
return NULL;

file.Close();
hdib = ReadDibBitmapInfoFromStream(pstrmOutMem);
//ReadDibBitmapInfo 라는 함수가 있는데 이것은 화일 핸들로 파라미터로
//받는데 단지 Stream 을 받을수 있도록 수정했을뿐 내부 내용은
//ReadDibBitmapInfo 가 같습니다.
if (!hdib)
return NULL;
DibInfo(hdib,&bi);

/* Calculate the memory needed to hold the DIB */
dwBits = bi.biSizeImage;
dwLen = bi.biSize + (DWORD)PaletteSize (&bi) + dwBits;

/* Try to increase the size of the bitmap info. buffer to hold the DIB */
h = GlobalReAlloc(hdib, dwLen, GHND);
if (!h){
GlobalFree(hdib);
hdib = NULL;
}
else
hdib = h;

/* Read in the bits */
if (hdib){

lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib);

pstrmOutMem->Read((LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi), dwBits, &cbRead);
GlobalUnlock(hdib);
}
}
catch (_com_error e){

}

return hdib;
}




이름 : 김서영 번호 : 52 게시일 : 1999.10.15 18:39:58 조회 : 196

안녕하세요
김서영입니다.
전에 시삽님이 올려놓으라고 하셨는데 지금에서야 올립니다.
죄송합니다.
Codeguru에서 가져온건데 제가 따로있는것을 붙여서 조금 수정했습니다.
많이는 아니고요

감사합니다.

BOOL CDib::WriteWindowToDIB(CRect &rect, CSize &destSize,HANDLE& hDIB, UINT& size)
{
CBitmap bitmap;
CDC memDC,screenDC;

screenDC.CreateDC("DISPLAY",NULL,NULL,NULL);
memDC.CreateCompatibleDC(&screenDC);
bitmap.CreateCompatibleBitmap(&screenDC, destSize.cx, destSize.cy);
CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);
//영역에 대한 캡쳐 BitBlt를 이용해도 되는데..........
memDC.StretchBlt(0,
0,
destSize.cx,
destSize.cy,
&screenDC,
rect.left,
rect.top,
rect.Width(),
rect.Height(),
SRCCOPY);
CPalette pal;
//현재 해상도가 256칼라 이하라면 팔레트 추가
if( screenDC.GetDeviceCaps(RASTERCAPS) & RC_PALETTE )
{
UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * 256);
LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
pLP->palVersion = 0x300;
pLP->palNumEntries = GetSystemPaletteEntries(
screenDC,
0,
255,
pLP->palPalEntry );
// Create the palette
pal.CreatePalette( pLP );
delete[] pLP;
}

memDC.SelectObject(pOldBitmap);

// Convert the bitmap to a DIB
hDIB = NULL;
hDIB = DDBToDIB(bitmap, BI_RGB, &pal , size);

screenDC.DeleteDC();

if( hDIB == NULL )
return FALSE;

return TRUE;
}

HANDLE CDib::DDBToDIB(CBitmap& bitmap, DWORD dwCompression, CPalette* pPal, UINT &size)
{
BITMAP bm;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
DWORD dwLen;
HANDLE hDIB;
HANDLE handle;
HDC hDC;
HPALETTE hPal;

ASSERT( bitmap.GetSafeHandle() );

// The function has no arg for bitfields
if( dwCompression == BI_BITFIELDS )
return NULL;

// If a palette has not been supplied use defaul palette
hPal = (HPALETTE) pPal->GetSafeHandle();
if (hPal==NULL)
hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);

// Get bitmap information
bitmap.GetObject(sizeof(bm),(LPSTR)&bm);

// Initialize the bitmapinfoheader
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = bm.bmPlanes * bm.bmBitsPixel;
bi.biCompression = dwCompression;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;

// Compute the size of the infoheader and the color table
int nColors = (1 << bi.biBitCount);
if( nColors > 256 )
nColors = 0;
dwLen = bi.biSize + nColors * sizeof(RGBQUAD);

// We need a device context to get the DIB from
hDC = ::GetDC(NULL);
hPal = SelectPalette(hDC,hPal,FALSE);
RealizePalette(hDC);

// Allocate enough memory to hold bitmapinfoheader and color table
hDIB = GlobalAlloc(GMEM_FIXED,dwLen);

if (!hDIB){
SelectPalette(hDC,hPal,FALSE);
::ReleaseDC(NULL,hDC);
return NULL;
}

lpbi = (LPBITMAPINFOHEADER)hDIB;

*lpbi = bi;

// Call GetDIBits with a NULL lpBits param, so the device driver
// will calculate the biSizeImage field
GetDIBits(hDC,
(HBITMAP)bitmap.GetSafeHandle(),
0L,
(DWORD)bi.biHeight,
(LPBYTE)NULL,
(LPBITMAPINFO)lpbi,
(DWORD)DIB_RGB_COLORS);

bi = *lpbi;

// If the driver did not fill in the biSizeImage field, then compute it
// Each scan line of the image is aligned on a DWORD (32bit) boundary
if (bi.biSizeImage == 0){
bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / Cool
* bi.biHeight;

// If a compression scheme is used the result may infact be larger
// Increase the size to account for this.
if (dwCompression != BI_RGB)
bi.biSizeImage = (bi.biSizeImage * 3) / 2;
}

// Realloc the buffer so that it can hold all the bits
dwLen += bi.biSizeImage;
if (handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE))
hDIB = handle;
else{
GlobalFree(hDIB);

// Reselect the original palette
SelectPalette(hDC,hPal,FALSE);
::ReleaseDC(NULL,hDC);
return NULL;
}

// Get the bitmap bits
lpbi = (LPBITMAPINFOHEADER)hDIB;

// FINALLY get the DIB
BOOL bGotBits = GetDIBits( hDC,
(HBITMAP)bitmap.GetSafeHandle(),
0L, // Start scan line
(DWORD)bi.biHeight, // # of scan lines
(LPBYTE)lpbi // address for bitmap bits
+ (bi.biSize + nColors * sizeof(RGBQUAD)),
(LPBITMAPINFO)lpbi, // address of bitmapinfo
(DWORD)DIB_RGB_COLORS);// Use RGB for color table

if( !bGotBits )
{
GlobalFree(hDIB);

SelectPalette(hDC,hPal,FALSE);
::ReleaseDC(NULL,hDC);
return NULL;
}

SelectPalette(hDC,hPal,FALSE);
::ReleaseDC(NULL,hDC);
size = dwLen;

return hDIB;
}

//*******************************************************
// 팔레트 생성
//********************************************************
BOOL CDib::CreatePalette(HGLOBAL* hDIB, CPalette *pPal)
{
//수신된 데이타 영역에서 비트맵 정보영역을 추출
BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;

//몇가지 색상을 사용하는지
int nColors = bmInfo.bmiHeader.biClrUsed ? bmInfo.bmiHeader.biClrUsed :
1 << bmInfo.bmiHeader.biBitCount;
// 256칼라 이하일때 팔레트의 생성
if( nColors <= 256 )
{
UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
if( !(pLP)) pLP = (LOGPALETTE *) new BYTE[nSize];
if(pLP)
{
pLP->palVersion = 0x300;
pLP->palNumEntries = nColors;
}else return FALSE;

for( int i=0; i < nColors; i++)
{
pLP->palPalEntry[i].peRed = bmInfo.bmiColors[i].rgbRed;
pLP->palPalEntry[i].peGreen = bmInfo.bmiColors[i].rgbGreen;
pLP->palPalEntry[i].peBlue = bmInfo.bmiColors[i].rgbBlue;
pLP->palPalEntry[i].peFlags = 0;
}
pPal->CreatePalette( pLP );

delete[] pLP;
}
return TRUE;
}
IE가 죽을 때 트레이의 아이콘이 모두 사라지는 경우가 있습니다.
특히 트레이에 숨어버리는 프로그램이 그렇게 되면 참으로 난감해지죠.

IE 4이상에서는 그런 일을 막기 위해서 죽은 후 태스크바가 만들어질 때 모든 top-level 윈도우에 메시지를 보내줍니다. 그 메시지를 받으면 트레이에 새로 아이콘을 넣어주면 됩니다.

MSDN에 있는 내용이지만 모르시는 분들이 많더군요.

소스를 보면 다음과 같습니다.

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
static UINT s_uTaskbarRestart;

switch(uMessage)
{
case WM_CREATE:
s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
break;

default:
if(uMessage == s_uTaskbarRestart)
AddTaskbarIcons();
break;
}
return DefWindowProc(hWnd, uMessage, wParam, lParam);
}

RegisterWindowMessage(TEXT("TaskbarCreated")); 는 TaskbarCreated라는 이름의 메시지를 시스템에 대해서 유일하게 만들어주는 함수입니다. 이미 이 이름으로 메시지가 등록되어 있을 경우에는 그 값을 돌려줍니다.
따라서 프로그램이 시작할 때 한번 실행해서 그 값을 저장해줘야 합니다.
그리고 해당 메시지가 오면 그 때 트레이에 아이콘을 새로 넣으면 되겠죠.

MFC의 경우는 메시지의 값이 상수로 정해져 있지 않기 때문에 메시지 맵에 붙이는 건 안될 것 같습니다. CWnd::WindowProc이나 PretranslateMessage에서 메시지 값을 확인해서 처리해주면 되겠죠.
class CMemDC : public CDC {
private:
CBitmap* m_bitmap;
CBitmap* m_oldBitmap;
CDC* m_pDC;
CRect m_rcBounds;
public:
CMemDC(CDC* pDC, const CRect& rcBounds) : CDC()
{
CreateCompatibleDC(pDC);
m_bitmap = new CBitmap;
m_bitmap->CreateCompatibleBitmap(pDC, rcBounds.Width(), rcBounds.Height());
m_oldBitmap = SelectObject(m_bitmap);
m_pDC = pDC;
m_rcBounds = rcBounds;
}
~CMemDC()
{
m_pDC->BitBlt(m_rcBounds.left, m_rcBounds.top, m_rcBounds.Width(), m_rcBounds.Height(),
this, m_rcBounds.left, m_rcBounds.top, SRCCOPY);
SelectObject(m_oldBitmap);
if (m_bitmap != NULL) delete m_bitmap;
}
CMemDC* operator->() {
return this;
}
};


OnDraw(){
CRect rect;
GetClientRect(&rect);
CMemDC dc(pDC, rect);
dc->FillRect(rect, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));

// TODO: add draw code for native data here
}
double angle(CPoint Cen,CPoint First,CPoint Second)
{
CClientDC dc(this);
double lega1,lega2,legb1,legb2;
double norm,norm1,norm2,angle,prod,curl;
int x1,y1,x2,y2,x3,y3;

x2 = Cen.x; y2 = Cen.y;
x1 = First.x; y1 = First.y;
x3 = Second.x; y3 = Second.y;

lega1 = x1-x2;
legb1 = y1-y2;
lega2 = x3-x2;
legb2 = y3-y2;

norm1 = sqrt(lega1*lega1+legb1*legb1);//두 벡터의 크기
norm2 = sqrt(lega2*lega2+legb2*legb2);//두 벡터의 크기
norm = norm1 * norm2;
prod = (lega1*lega2)+(legb1*legb2);//두 벡터의 내적
angle = acos(prod/norm);

curl = (lega1*legb2)-(legb1*lega2);//두 벡터의 외적

if (curl<=0) return angle/3.141592654*180;

else return (360-angle/3.141592654*180);
}
class SC_Rotate_Line
{
public:
dxy_t sc_Begin, sc_End;
double sc_Angle;
dxy_t sc_LeftPoint;
public:
SC_Rotate_Line() {}
SC_Rotate_Line(dxy_t Begin,dxy_t End, float Angle, CDC* pDC)
{
sc_Begin = Begin;
sc_End = End;
sc_Angle = -Angle/180*PI;

sc_LeftPoint.x = cos(sc_Angle)*(sc_End.x - sc_Begin.x) - sin(sc_Angle)*(sc_End.y - sc_Begin.y);
sc_LeftPoint.y = sin(sc_Angle)*(sc_End.x - sc_Begin.x) + cos(sc_Angle)*(sc_End.y - sc_Begin.y);
sc_LeftPoint.x = sc_LeftPoint.x + sc_Begin.x;
sc_LeftPoint.y = sc_LeftPoint.y + sc_Begin.y;

pDC->MoveTo(long(sc_Begin.x+0.5), long(sc_Begin.y+0.5));
pDC->LineTo(long(sc_LeftPoint.x+0.5), long(sc_LeftPoint.y+0.5));
}
SC_Rotate_Line(double Beginx,double Beginy,double Endx,double Endy ,float Angle, CDC* pDC)
{
sc_Begin.x = Beginx;
sc_Begin.y = Beginy;
sc_End.x = Endx;
sc_End.y = Endy;
sc_Angle = -Angle/180*PI;

sc_LeftPoint.x = cos(sc_Angle)*(sc_End.x - sc_Begin.x) - sin(sc_Angle)*(sc_End.y - sc_Begin.y);
sc_LeftPoint.y = sin(sc_Angle)*(sc_End.x - sc_Begin.x) + cos(sc_Angle)*(sc_End.y - sc_Begin.y);
sc_LeftPoint.x = sc_LeftPoint.x + sc_Begin.x;
sc_LeftPoint.y = sc_LeftPoint.y + sc_Begin.y;

pDC->MoveTo(long(sc_Begin.x+0.5), long(sc_Begin.y+0.5));
pDC->LineTo(long(sc_LeftPoint.x+0.5), long(sc_LeftPoint.y+0.5));
}
SC_Rotate_Line(CPoint Begin, CPoint End, float Angle, CDC* pDC)
{
sc_Begin.x = Begin.x;
sc_Begin.y = Begin.y;
sc_End.x = End.x;
sc_End.y = End.y;
sc_Angle = -Angle/180*PI;

sc_LeftPoint.x = cos(sc_Angle)*(sc_End.x - sc_Begin.x) - sin(sc_Angle)*(sc_End.y - sc_Begin.y);
sc_LeftPoint.y = sin(sc_Angle)*(sc_End.x - sc_Begin.x) + cos(sc_Angle)*(sc_End.y - sc_Begin.y);
sc_LeftPoint.x = sc_LeftPoint.x + sc_Begin.x;
sc_LeftPoint.y = sc_LeftPoint.y + sc_Begin.y;

pDC->MoveTo(long(sc_Begin.x+0.5), long(sc_Begin.y+0.5));
pDC->LineTo(long(sc_LeftPoint.x+0.5), long(sc_LeftPoint.y+0.5));
}
CPoint SC_Return(CPoint Begin, CPoint End, double Angle)
{
sc_Begin.x = Begin.x;
sc_Begin.y = Begin.y;
sc_End.x = End.x;
sc_End.y = End.y;
sc_Angle = -Angle/180*PI;

sc_LeftPoint.x = cos(sc_Angle)*(sc_End.x - sc_Begin.x) - sin(sc_Angle)*(sc_End.y - sc_Begin.y);
sc_LeftPoint.y = sin(sc_Angle)*(sc_End.x - sc_Begin.x) + cos(sc_Angle)*(sc_End.y - sc_Begin.y);
sc_LeftPoint.x = sc_LeftPoint.x + sc_Begin.x;
sc_LeftPoint.y = sc_LeftPoint.y + sc_Begin.y;

return CPoint(long(sc_LeftPoint.x+0.5), long(sc_LeftPoint.y+0.5));
}
};

예전 학창시절에 만들었던건데.. 자료가 있길래 올려본다.

class SC_Arrow
{
public:
dxy_t sc_Begin, sc_End;
double sc_Angle;
dxy_t sc_LeftPoint, sc_RightPoint;
dxy_t sc_Increasement;
public:
SC_Arrow() {}
SC_Arrow(dxy_t Begin,dxy_t End,CDC* pDC,float Angle = 20.)
{
sc_Begin = Begin;
sc_End = End;
sc_Angle = Angle/180*PI;

sc_Increasement.x = (sc_End.x - sc_Begin.x)*(-1./10.);
sc_Increasement.y = (sc_End.y - sc_Begin.y)*(-1./10.);


sc_LeftPoint.x = cos(sc_Angle)*sc_Increasement.x - sin(sc_Angle)*sc_Increasement.y;
sc_LeftPoint.y = sin(sc_Angle)*sc_Increasement.x + cos(sc_Angle)*sc_Increasement.y;
sc_LeftPoint.x = sc_LeftPoint.x + sc_End.x;
sc_LeftPoint.y = sc_LeftPoint.y + sc_End.y;
sc_RightPoint.x = cos(sc_Angle)*sc_Increasement.x + sin(sc_Angle)*sc_Increasement.y;
sc_RightPoint.y = -sin(sc_Angle)*sc_Increasement.x + cos(sc_Angle)*sc_Increasement.y;
sc_RightPoint.x = sc_RightPoint.x + sc_End.x;
sc_RightPoint.y = sc_RightPoint.y + sc_End.y;

pDC->MoveTo(long(sc_Begin.x+0.5), long(sc_Begin.y+0.5));
pDC->LineTo(long(sc_End.x+0.5), long(sc_End.y+0.5));
pDC->LineTo(long(sc_LeftPoint.x+0.5), long(sc_LeftPoint.y+0.5));
pDC->MoveTo(long(sc_End.x+0.5), long(sc_End.y+0.5));
pDC->LineTo(long(sc_RightPoint.x+0.5),long(sc_RightPoint.y+0.5));
}
SC_Arrow(CPoint Begin,CPoint End,CDC* pDC,float Angle = 20.)
{
sc_Begin.x = Begin.x;
sc_Begin.y = Begin.y;
sc_End.x = End.x;
sc_End.y = End.y;
sc_Angle = Angle/180*PI;

sc_Increasement.x = (sc_End.x - sc_Begin.x)*(-1./10.);
sc_Increasement.y = (sc_End.y - sc_Begin.y)*(-1./10.);


sc_LeftPoint.x = cos(sc_Angle)*sc_Increasement.x - sin(sc_Angle)*sc_Increasement.y;
sc_LeftPoint.y = sin(sc_Angle)*sc_Increasement.x + cos(sc_Angle)*sc_Increasement.y;
sc_LeftPoint.x = sc_LeftPoint.x + sc_End.x;
sc_LeftPoint.y = sc_LeftPoint.y + sc_End.y;
sc_RightPoint.x = cos(sc_Angle)*sc_Increasement.x + sin(sc_Angle)*sc_Increasement.y;
sc_RightPoint.y = -sin(sc_Angle)*sc_Increasement.x + cos(sc_Angle)*sc_Increasement.y;
sc_RightPoint.x = sc_RightPoint.x + sc_End.x;
sc_RightPoint.y = sc_RightPoint.y + sc_End.y;

pDC->MoveTo(long(sc_Begin.x+0.5), long(sc_Begin.y+0.5));
pDC->LineTo(long(sc_End.x+0.5), long(sc_End.y+0.5));
pDC->LineTo(long(sc_LeftPoint.x+0.5), long(sc_LeftPoint.y+0.5));
pDC->MoveTo(long(sc_End.x+0.5), long(sc_End.y+0.5));
pDC->LineTo(long(sc_RightPoint.x+0.5),long(sc_RightPoint.y+0.5));
}
SC_Arrow(double Beginx,double Beginy,double Endx,double Endy ,CDC* pDC,float Angle = 20.)
{
sc_Begin.x = Beginx;
sc_Begin.y = Beginy;
sc_End.x = Endx;
sc_End.y = Endy;
sc_Angle = Angle/180*PI;

sc_Increasement.x = (sc_End.x - sc_Begin.x)*(-1./10.);
sc_Increasement.y = (sc_End.y - sc_Begin.y)*(-1./10.);


sc_LeftPoint.x = cos(sc_Angle)*sc_Increasement.x - sin(sc_Angle)*sc_Increasement.y;
sc_LeftPoint.y = sin(sc_Angle)*sc_Increasement.x + cos(sc_Angle)*sc_Increasement.y;
sc_LeftPoint.x = sc_LeftPoint.x + sc_End.x;
sc_LeftPoint.y = sc_LeftPoint.y + sc_End.y;
sc_RightPoint.x = cos(sc_Angle)*sc_Increasement.x + sin(sc_Angle)*sc_Increasement.y;
sc_RightPoint.y = -sin(sc_Angle)*sc_Increasement.x + cos(sc_Angle)*sc_Increasement.y;
sc_RightPoint.x = sc_RightPoint.x + sc_End.x;
sc_RightPoint.y = sc_RightPoint.y + sc_End.y;

pDC->MoveTo(long(sc_Begin.x+0.5), long(sc_Begin.y+0.5));
pDC->LineTo(long(sc_End.x+0.5), long(sc_End.y+0.5));
pDC->LineTo(long(sc_LeftPoint.x+0.5), long(sc_LeftPoint.y+0.5));
pDC->MoveTo(long(sc_End.x+0.5), long(sc_End.y+0.5));
pDC->LineTo(long(sc_RightPoint.x+0.5),long(sc_RightPoint.y+0.5));
}
};

+ Recent posts