윈도우/리눅스/유닉스 지원
멀티 캐스트 지원


이넘은 콜롬비아 싱글콜 UA 소스임당..

당근 엔진도 있죠..


코드로 구현해본 간단한 알파 블렌딩이다.

숫자 연산으로 표현된다.


현재 이넘은 윈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에서 메시지 값을 확인해서 처리해주면 되겠죠.
사용자 정보를 입력하면..

그 사용자가 속한 그룹을 읽어 오른 일련의 루틴과...

데브피아에서 찾은

단지 Administrator 인지만 확인하는 루틴..

크게 이 두가지로 구성되어 있다...

유용한 정보가 될것이다.


드래그 엔 드롭을 지원하는 콤보 박스입니다.

까막이 세상에서 첨으로 만든 겁니다.. ^^;


+ Recent posts