분류 전체보기
- [자료] 콜롬비아 RTP 소스(멀티캐스티) 2007.05.22
- [자료] 콜롬비아 SIP 소스 2007.05.22
- [자료] 간단한 알파블렌딩 개념 2007.05.22
- [팁] 폴더의 공유 정보창 띄우기 2007.05.22
- [팁] 풀 스크린 (SDI/ MDI) 2007.05.22
- [팁] 파일에 연결된 프로그램 경로 읽어오기 2007.05.22
- [팁] 윈도화면 캡쳐해서 압축 저장하기 2007.05.22
- [팁] 트레이아이콘 사라지는것 막기 2007.05.22
- [자료] 윈도우 유저와 그룹 정보 읽어오기 2007.05.22
- [자료] Drag & Drop ComboBox 2007.05.22
[자료] 콜롬비아 RTP 소스(멀티캐스티)
2007. 5. 22. 13:22
[자료] 콜롬비아 SIP 소스
2007. 5. 22. 13:21
[자료] 간단한 알파블렌딩 개념
2007. 5. 22. 13:19
[팁] 폴더의 공유 정보창 띄우기
2007. 5. 22. 13:18
현재 이넘은 윈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);
}
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);
}
[팁] 풀 스크린 (SDI/ MDI)
2007. 5. 22. 13:18
[팁] 파일에 연결된 프로그램 경로 읽어오기
2007. 5. 22. 13:18
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;
}
{
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;
}
[팁] 윈도화면 캡쳐해서 압축 저장하기
2007. 5. 22. 13:17
약속한데로... 자세한 설명을 해 드리죠.
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) /
* 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;
}
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) /
* 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;
}
[팁] 트레이아이콘 사라지는것 막기
2007. 5. 22. 13:17
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에서 메시지 값을 확인해서 처리해주면 되겠죠.
특히 트레이에 숨어버리는 프로그램이 그렇게 되면 참으로 난감해지죠.
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에서 메시지 값을 확인해서 처리해주면 되겠죠.
[자료] 윈도우 유저와 그룹 정보 읽어오기
2007. 5. 22. 13:15
사용자 정보를 입력하면..
그 사용자가 속한 그룹을 읽어 오른 일련의 루틴과...
데브피아에서 찾은
단지 Administrator 인지만 확인하는 루틴..
크게 이 두가지로 구성되어 있다...
유용한 정보가 될것이다.
그 사용자가 속한 그룹을 읽어 오른 일련의 루틴과...
데브피아에서 찾은
단지 Administrator 인지만 확인하는 루틴..
크게 이 두가지로 구성되어 있다...
유용한 정보가 될것이다.
[자료] Drag & Drop ComboBox
2007. 5. 22. 13:14