'3. Implementation/Windows API'에 해당되는 글 40건
- 2011.08.16 GetAsyncKeyState 사용법
- 2010.12.17 Execute Applications on Remote Systems - PsEXEC
- 2010.12.08 What is the difference between HINSTANCE and HMODULE?
- 2010.10.22 Create a movie from an HBitmap
- 2010.04.21 Download a File Using URLDownloadToCacheFile
- 2010.03.08 OutputDebugString 캡처하기 - DebugView 를 만들어보자
- 2010.02.05 Video For Windows Single-Frame Capture Class Without MFC
- 2009.11.27 Execute Applications on Remote Systems
- 2009.10.12 PostThreadMessage 함수
- 2009.10.12 Window 에서 Owner 관계
- 2009.10.11 SignalObjectAndWait 함수
- 2009.10.11 Sleep 과 SwichToThread 함수
- 2009.10.11 WaitForInputIdle 함수 1
- 2009.08.28 클립보드(Clipboard)에 비트맵 저장 & 로드
- 2009.07.04 EXE 안에 외부의 데이터파일 저장하기
- 2009.07.03 간단하게 취소 기능 구현하기
- 2009.04.09 WPARAM 과 LPARAM
- 2009.03.06 MsgWaitForMultipleObjects and the queue state
- 2008.12.10 Obtaining Directory Change Notifications
- 2008.12.10 소멸자를 이용한 뮤텍스 권한 소유 및 해제
if (GetAsyncKeyState(VK_SHIFT) & 0x8000) { // The key is currently down }
unsigned char KeyStates[256]; GetKeyboardState(KeyStates); for (int i = 0; i < 256; i++) { if (KeyStates[i] & 0x8000) { // The keyboard key that 'i' represents is currently held down. } }
출처: http://cboard.cprogramming.com/cplusplus-programming/112970-getasynckeystate-key-pressed.html
Execute Applications on Remote Systems - PsEXEC

출처: http://www.codeguru.com/cpp/i-n/network/remoteinvocation/article.php/c5433
Environment: NT4 SP6, Win 2000 SP1, Visual C++ 6.0
Overview
This program allows you to execute applications on remote systems without installing any client software. You can start a command prompt or just execute a command or exe on a remote machine. The only restriction is you must be an administrator :(
Everybody knows the cool tools from Sysinternals (www.sysinternals.com). One of my favorites are PSEXEC, PSKILL and PSLIST,... :)
I was always wonder how they could query every kind of information or execute commands on a remote machine without installing any client software.
Features
- With this program you can run as many remote commands on the remote machine as you want. (PSEXEC supports only one remote command on the remote machine at the same time)
- You can execute internal commands (dir,..) directly.
xCmd.exe \\remote dir - You can start a light "telnet" connection with a remote machine without any telnet server
xCmd.exe \\remote cmd
Usage
xCmd v1.0 for NT4/2000 - executes commands remotely
Freeware! 2001 Zoltan Csizmadia, zoltan_csizmadia@yahoo.com
Usage: xCmd.exe \\computer [options] command/exe arguments
Options:
/D:directory Set working directory
Default: Remote "%SystemRoot%\System32"
/IDLE Idle priority class
/NORMAL Normal priority class
/HIGH High priority class
/REALTIME Realtime priority class
/C Copy the specified program to the remote machine's
"%SystemRoot%\System32" directory
Commands's exe file must be absolute to local machine
/USER:user User for remote connection
/PWD:{password|*} Password for remote connection
/NOWAIT Don't wait for remote process to terminate
Examples:
xCmd.exe \\remote cmd
xCmd.exe \\remote /user:administrator dir c:\
xCmd.exe \\remote /user:somebody /pwd:* /d:d:\ test1.exe /p1 /p2
xCmd.exe \\remote /c /user:somebody /pwd:* /d:d:\ test2.exe /whatever
- Input is passed to remote machine when you press the ENTER.
- Ctrl-C terminates the remote process
- Command and file path arguments have to be absolute to remote machine
If you are using /c option, command exe file path must be absolute to
local machine, but the arguments must be absolute to remote machine
How does it work?
- The xCmd.exe is console application and when you start it, the program will extract a xCmdSvc.exe from its resources.
- xCmd.exe creates a service on the remote machine (that's the reason, you must be an administrator
- xCmd.exe starts the remote service (#2)
- xCmd.exe and xCmdSvc.exe will communicate via named pipes
- xCmd.exe send a packet to the service what to execute
- xCmdSvc.exe starts the command and redirect stdout, stderr, stdin to 3 named pipes.
- xCmd.exe listens these 3 named pipes (#6), redirect them to its stdout, stderr, stdin
Notes
So if you get some errors, rebuild your executable from the source (xCmd.dsw).
What is the difference between HINSTANCE and HMODULE?

They mean the same thing today, but at one time they were quite different.
It all comes from 16-bit Windows.
In those days, a "module" represented a file on disk that had been loaded into memory, and the module "handle" was a handle to a data structure that described the parts of the file, where they come from, and where they had been loaded into memory (if at all). On the other hand an "instance" represented a "set of variables".
One analogy that might (or might not) make sense is that a "module" is like the code for a C++ class - it describes how to construct an object, it implements the methods, it describes how the objects of the class behave. On the other hand, an "instance" is like a C++ object that belongs to that class - it describes the state of a particular instance of that object.
In C# terms, a "module" is like a "type" and an instance is like an "object". (Except that modules don't have things like "static members", but it was a weak analogy anyway.)
Here's a diagram. (Recall that we discussed 16-bit HRSRC in a previous entry.)
USER32 HMODULE | USER32 HINSTANCE | |||
code segment descriptor | USER32 code... | USER32 data... | ||
code segment descriptor | (not in memory) | |||
code segment descriptor | USER32 code... | |||
data segment descriptor | ||||
HRSRC | (not in memory) | |||
HRSRC | USER32 resource... | |||
HRSRC | (not in memory) | |||
exports table |
In 16-bit Windows, all programs ran in a single address space, and if a DLL was used by five programs, it was loaded only once into memory. In particular, it got only one copy of its data segment. (In C++/C# terms, a DLL is like a "singleton class".)
That's right, DLLs were system-global rather than per-process. The DLL did not get a separate copy of its data for each process that loaded it. If that was important to your DLL, you had to keep track of it yourself.
In geek terms, there was only one "instance" of a DLL in the system.
On the other hand, if you ran two copies of Notepad, each one got its separate set of variables - there were two "instances".
NOTEPAD HMODULE | HINSTANCE | |||
code segment descriptor | NOTEPAD code... | NOTEPAD data... | ||
code segment descriptor | (not in memory) | |||
data segment descriptor | HINSTANCE | |||
HRSRC | (not in memory) | NOTEPAD data... | ||
HRSRC | NOTEPAD resource... |
Both running copies of Notepad shared the NOTEPAD module (so the code and resources were shared), but each had its own copy of its variables (separate data segment). There were two "instances" of Notepad.
The "instance" handles in the above diagrams are the data segments.
Programs are identified by their the instance handle. You can't use the module handle, because the two copies of Notepad have the same module handle (since the same code is running in each). The thing that makes them different is that each has its own set of global variables.
This is why the WinExec and ShellExecute functions return HINSTANCE: They are holdovers from 16-bit Windows, where HINSTANCEs were the way to identify running programs.
The method by which code receives its HINSTANCE (i.e., knows where its global variables are) I will leave for a future article. It is somehow related to the now-obsolete MakeProcInstance function.
When it came to design Win32, the question then arose, "What do we do with HINSTANCE and HMODULE for Win32?" Since programs ran in separate address spaces, you didn't have instance handles visible across process boundaries. So the designers took the only thing they had: The base address of the module. This was analogous to the HMODULE, since the file header describes the contents of the file and its structure. And it was also analogous to the HINSTANCE, since the data was kept in the data segment, which was mapped into the process directly.
So in Win32, HINSTANCE and HMODULE are both just the base address of the module.
Tomorrow, I'll talk about that mysterious hinstPrev parameter to WinMain.
원문: http://blogs.msdn.com/b/oldnewthing/archive/2004/06/14/155107.aspx
Create a movie from an HBitmap

Download a File Using URLDownloadToCacheFile

::URLDownloadToCacheFile()
or ::URLDownloadToFile()
functions. The URL functions combine the
capabilities of asynchronous monikers and URL monikers into easy-to-use functions. By using
these functions, you do not have to worry about the protocols used to transfer the files,
such as HTTP, FTP. In the simplest case, all you have to do is to pass them the URL.
::URLDownloadToCacheFile()
downloads data into the Internet cache and returns the file name of
the cache location for retrieving the bits. ::URLDownloadToFile()
downloads bits from the
Internet and saves them to a file. However, they are blocking functions. Even though the data
is downloaded asynchronously the functions do not return until all the data is downloaded.
You can choose to be notified of progress through a notification callback.......
http://www.codeproject.com/KB/IP/urlfile.aspx
OutputDebugString 캡처하기 - DebugView 를 만들어보자

//////////////////////////////////////////////////////////////////////////////////////////////// struct DbWinBuffer { DWORD dwProcessId; char data[4096 - sizeof(DWORD)]; }; DbWinBuffer* dbBuffer; HANDLE hAckEvent; HANDLE hEvent; HANDLE hSharedFile; SECURITY_DESCRIPTOR sd; SECURITY_ATTRIBUTES sa; //////////////////////////////////////////////////////////////////////////////////////////////// sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = true; sa.lpSecurityDescriptor = &sd; if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { printf("ERROR: InitializeSecurityDescriptor\\n"); return 1; } if (!SetSecurityDescriptorDacl(&sd, true, 0, false)) { printf("ERROR: SetSecurityDescriptorDacl\n"); return 1; } hAckEvent = CreateEvent(&sa, false, false, L"DBWIN_BUFFER_READY"); if (!hAckEvent) { printf("ERROR: CreateEvent(\\"DBWIN_BUFFER_READY\\")\\n"); return 1; } hEvent = CreateEvent(&sa, false, false, L"DBWIN_DATA_READY"); if (!hEvent) { printf("ERROR: CreateEvent(\\"DBWIN_DATA_READY\\")\\n"); return 1; } hSharedFile = CreateFileMapping((HANDLE)-1, &sa, PAGE_READWRITE, 0, 4096, L"DBWIN_BUFFER"); if(!hSharedFile) { printf("ERROR: CreateFileMapping(\\"DBWIN_BUFFER\\")\\n"); return 1; } dbBuffer = static_cast<DbWinBuffer*>(MapViewOfFile(hSharedFile, FILE_MAP_READ, 0, 0, 4096)); if(!dbBuffer) { printf("ERROR: MapViewOfFile\\n"); return 1; } SetEvent(hAckEvent); DWORD pid = GetCurrentProcessId(); printf("Tracing PID: %dnn", pid); for(;;) { DWORD ret = WaitForSingleObject(hEvent, INFINITE); if (ret == WAIT_FAILED) { printf("ERROR: WaitForSingleObject\\n"); return 1; } if (dbBuffer->dwProcessId == pid) { printf("%s", dbBuffer->data); } SetEvent(hAckEvent); } |
http://www.devmaster.net/forums/showthread.php?t=11229
Video For Windows Single-Frame Capture Class Without MFC

출처 : http://www.codeguru.com/cpp/g-m/multimedia/video/article.php/c4723/
Execute Applications on Remote Systems

Zoltan Csizmadia (view profile) April 13, 2001 |
.
Environment: NT4 SP6, Win 2000 SP1, Visual C++ 6.0
Overview
xCmd v1.0 for NT4/2000 - executes commands remotely The executable is compiled and linked on Windows 2000 SP1, VC++ 6.0 SP4 and
in multithreaded DLL mode.Features
xCmd.exe \\remote dir
xCmd.exe \\remote cmdUsage
Freeware! 2001 Zoltan Csizmadia, zoltan_csizmadia@yahoo.com
Usage: xCmd.exe \\computer [options] command/exe arguments
Options:
/D:directory
Set working directory
Default: Remote "%SystemRoot%\System32"
/IDLE
Idle priority class
/NORMAL
Normal priority class
/HIGH
High priority class
/REALTIME
Realtime priority class
/C
Copy the specified program to the remote machine's
"%SystemRoot%\System32" directory
Commands's exe file must be absolute to local machine
/USER:user
User for remote connection
/PWD:{password|*} Password for remote
connection
/NOWAIT
Don't wait for remote process to terminate
Examples:
xCmd.exe \\remote cmd
xCmd.exe \\remote /user:administrator dir c:\
xCmd.exe \\remote /user:somebody /pwd:* /d:d:\ test1.exe
/p1 /p2
xCmd.exe \\remote /c /user:somebody /pwd:* /d:d:\ test2.exe
/whatever
- Input is passed to remote machine when you press the ENTER.
- Ctrl-C terminates the remote process
- Command and file path arguments have to be absolute to remote machine
If you are using /c option, command exe file path must be absolute to
local machine, but the arguments must be absolute to remote machineHow does it work?
Notes
So if you get some errors, rebuild your executable from the source (xCmd.dsw).
From : http://www.codeguru.com/cpp/i-n/network/remoteinvocation/article.php/c5433/
다른 스레드의 메시지 큐에 메시지를 붙일 때 사용한다. 윈도우 핸들 대신 스레드의 ID 를 첫 번째 인수로 지정해 준다. 이때 이 메시지를 받을 스레드는 반드시 스레드 큐를 가지고 있어야 하는데 큐를 가지지 않는 Worker 스레드는 메시지를 받지 못한다.
[그림] PostMessage 와 SendMessage 가 메시지를 넣는 지점
참고 : Windows API 정복 - 김상형


소유된 윈도우는 소유자보다 항상 화면상의 위에 위치하며 소유자가 숨거나 파괴되면 같이 숨겨지고 파괴된다. 그러나 소유자의 이동은 소유된 윈도우에 아무런 영향도 주지 않는다. 윈도우간의 소유 관계는 CreateWindow 함수의 hwndParent 인수로 지정하는데 단 hwndParent 가 차일드 윈도우인 경우는 그 차일드가 소유자가 되지 않고 차일드를 소유하고 있는 윈도우가 소유자가 된다.
부모-자식 관계와, 소유자 관계의 또 다른 차이점은 부모는 실행중에 SetParent 함수로 변경할 수 있지만 소유 관계는 한번 설정되고 난 후에 변경할 수 없다는 점이다.
소유자 윈도우를 조사할 때는 GetWindow 함수를 사용한다.
HWND GetWindow(HWND hwnd, UINT uCmd);
이 함수는 hWnd 윈도우와 uCmd 관계에 있는 윈도우를 구해 주는데 GW_CHILD 이면 첫 번째 차일드 윈도우를 구해 주며 GW_OWNER 이면 소유자 윈도우를 구해준다.
출처 : Windows API 정복 - 김상형 저
HANDLE hObjectToWaitOn,
HANDLE dwMilliseconds,
BOOL balertable);
이 함수는 두 가지 이유로 인해 윈도우에 추가되었다.
첫째로, 개발자들은 특정 오브젝트를 시그널 상태로 만들어준 후 다른 오브젝트를 대기하는 식의 코드를 자주 작성하게 되는데, 단일 함수로 이와 같은 작업을 수행하게 되면 수행 시간을 절약해 주는 효과가 있다.
둘째로, SignalObjectAndWait 함수를 이용하면 이 함수를 호출한 스레드가 대기 상태에 있음을 보증할 수 있기 때문에 PulseEvent 와 같은 함수를 사용할 때 유용하게 활용될 수 있다. PulseEvent 는 특정 이벤트를 시그널 상태로 변경하였다가 그 즉시 논시그널 상태로 변경하게 되는데, 어떠한 이벤트를 대기 중인 스레드가 없다면 이벤트가 시그널되었는지를 감지할 수가 없다. 이전에 누군가가 다음과 같은 코드를 작성한 것을 본 적이 있다.
// 작업을 수행한다.
SetEvent(hEventWorkerThreadDone);
WaitForSingleObject(hEventMoreWorkToBeDone, INFINITE);
// 추가 작업을 수행한다.
워커스레드는 작업을 완료 후 SetEvent 를 호출하여 작업을 모두 마쳤음을 다른 스레드에게 알려준다. 다른 스레드는 아마도 다음과 같은 코드를 수행하고 있었을 것이다.
WaitForSingleObject (hEventWorkderThreadDone);
PulseEvent(hEventMoreWorkToBeDone);
워커스레드가 수행하고 있는 코드는 정상 동작하지 않을 수 있는 나쁜 구조다. 워커 스레드가 SetEvent 를 호출하면 다른 스레드가 즉각 깨어나서 PuseEvent 를 호출할 것이라 생각하겠지만 워커 스레드가 SetEvent 를 호출하고 hEventMoreWorkToBeDone 을 매개변수로 WaitForSingleObject 를 호출하기 전에 수행 흐름이 다른 스레드로 변경될 수 있다. 이렇게 되면 PuseEvent 가 ㅁ너저 호출되어 hEventMoreWorkToBeDone 에 대한 시그널 후 논시그널로의 변경작업이 먼저 수행되기 때문에 워커 스레드는 SignalObjectAndWait 함수를 이용하여 아래와 같이 재작성될 수 있다. 이 코드는 시그널 상태로의 변경과 대기를 원자적으로 수행하기 때문에 앞서와 같은 문제를 유발하지 않는다.
// 작업을 수행한다.
SignalObjectAndWait(hEventWorkerThreadDone, hEventMoreWorkToBeDone, INFINITE, FALSE);
// 추가 작업을 수행한다.
이 함수를 호출한 직후 다른 스레드로 제어가 넘어간다 해도 워커 스레드가 hEventMoreWorkToBeDone 이벤트를 대기 중인 것을 100% 보장할 수 있으므로 PulseEvent 호출을 통한 이벤트 상태 변경은 항상 감지될 수 있게 된다.
출처 : 제프리 리처의 Windows via C/C++
일정 시간동안 자신을 스케줄하지 않도록 운영체제에게 명령을 내릴 수 있다.
- Sleep 을 호출하면 스레드는 자발적으로 남은 타임 슬라이스를 포기한다.
- Sleep 함수의 매개변수로 0을 전달할 수도 있다. 이렇게 하면 이 함수를 호출한 스레드가 남은 타임 슬라이스를 자발적으로 포기하여 시스템이 다른 스레들르 스케줄하게 한다. 그런데 시스템에 이 함수를 호출한 스레드와 우선순위가 같거나 그보다 높은 스레드 중에 스케줄 가능 스레드가 없는 경우 Sleep 함수를 호출한 스레드가 다시 스케줄 될 수도 있다.
BOOL SwitchToThread();
시스템은 일정 시간 동안 CPU 시간을 받지 못하여 수행되지 못하고 있던 스레드가 있는지 확인한다. 만일 그러한 스레드가 없다면 SwitchToThread 함수는 바로 반환되지만, 그러한 스레드가 존재한다면 SwitchToThread 는 해당 스레드를 스케줄 한다. 아마도 이러한 스레드는 SwitchToThread 함수를 호출한 스레드에 비해 낮은 우선순위를 가지고 있을 것이다. CPU 시간을 할당받은 스레드는 단일 퀀텀 시간 시간 동안만 수행되며, 이후 스케줄러는 이전과 동일하게 스케줄링을 수행한다.
이 함수를 이용하면 리소스를 소유하고 있는 낮은 우선순위의 스레드가 해당 리소스를 빨리 사용하고 반환할 수 있도록 해준다. SwitchToThread 를 호출하였을 때 수행할 스레드가 없다면 FALSE 를 반환하고, 그렇지 않은 경우 0이 아닌 값을 반환한다.
------
SwitchToThread 함수를 호출하는 것은 Sleep 함수를 호출할 때 인자로 0 밀리초의 타임아웃 값을 전달하는 것과 유사하다. 차이점이라면 SwitchToThread 의 경우 함수를 호출한 스레드보다 낮은 우선순위의 스레드들도 수행될 수 있다는 점일 것이다. Sleep 함수의 경우 설사 낮은 우선순위의 스레드들이 오랫동안 CPU 시간을 받지 못했다 하더라도 Sleep 함수를 호출한 스레드를 다시 스케줄링된다.
출처 : 제프리 리처의 Windows via c/c++
hProcess 가 가리키는 프로세스의 첫 번째 윈도우를 생성한 스레드가 대기 상태가 될 때까지 WaitForInputIdle 함수를 호출한 스레드를 대기 상태로 유지한다. 이 함수는 Parent 프로세스가 CreateProcess 를 호출하여 차일드 프로세스의 생성을 요청한 후 차일드 프로세스가 완전히 초기화될 때까지 대기하도록 하고 싶은 경우에 유용하게 사용될 수 있다. 예를 들어 Parent 프로세스의 스레드가 차일드 프로세스가 생성한 윈도우 핸들을 얻어오려면 언제 차일드 프로세스가 초기화를 완료하고 더 이상 처리할 입력이 없는지를 알아야 한다. 이를 위해 Parent 프로세스는 CreateProcess 를 호출한 이후에 WaitforInputIdle 함수를 호출하면 된다.
WaitForInputIdle 함수는 애플리케이션에 키 입력을 전송해야 할 필요가 있을 경우에도 유용하게 사용될 수 있다. 애플리케이션의 주 윈도우에 다음과 같은 일련의 메시지들을 Post 해야 할 경우를 생각해 보자.
WM_KEYDOWN | VK_MENU 가상 키 값을 인자로 함 |
WM_KEYDOWN | VK_F 가상 키 값을 인자로 함 |
WM_KEYUP | VK_F 가상 키 값을 인자로 함 |
WM_KEYUP | VK_MENU 가상 키 값을 인자로 함 |
WM_KEYDOWN | VK_O 가상 키 값을 인자로 함 |
WM_KEYUP | VK_O 가상 키 값을 인자로 함 |
대부분의 영어 기반 애플리케이션에서는 Alt+F, O 를 누르면 파일 메뉴의 열기 명령이 수행된다. 이러한 명령을 수행하면 보통 열기 다이얼로그 박스가 나타나는데, 이를 위해 윈도우는 다이얼로그 박스의 구조를 표현하고 있는 파일을 읽고 다이얼로그 박스 내의 각 컨트롤을 생성하기 위해 CreateWindow를 반복적으로 호출해야 한다. 이러한 과정은 상당한 시간을 소요하게 된다. 따라서 특정 애플리케이션에 WM_KEY 메시지를 포스트하려는 경우에는 WaitForInputIdle 함수를 호출하여 다이얼로그 박스가 완전히 생성되고 사용자 입력을 기다리는 상황이 될 때까지 대기해야 한다. 이후에 키 입력 메시지를 다이얼로그 박스에 전송해야만 수행하고자 하는 작업을 정확히 수행할 수 있다.
16비트 윈도우 애플리케이션을 개발하는 개발자의 경우 종종 이러한 문제를 겪게 될 것이다. 애플리케이션 메시지를 윈도우에 포스트하는 경우 언제 메시지가 처리되어 윈도우가 생성되고 메시지를 받아들일 준비가 될런지 알아내기가 쉽지 않다. 이 경우 WaitForInputIdle 함수를 사용하면 된다.
출처 : 제프리 리처의 Windows via C/c++
CMaptoolDoc* pDoc = GetDocument();
HANDLE hDIB;
BITMAPFILEHEADER bifileHdr;
BYTE* lptrData;
CClientDC dc(this); //클립보드로 현재 이미지를 전송
CDC MemDC;
MemDC.CreateCompatibleDC(&dc);
CRect rect;
GetClientRect(rect); //뷰 영역의 크기를 얻어온다
rect.right = pDoc->map_arr_x*(pDoc->tile_pixel_x+pDoc->view_size);
rect.bottom = pDoc->map_arr_y*(pDoc->tile_pixel_y+pDoc->view_size);
CBitmap BMP;
BMP.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());
CBitmap* pOldBitmap = MemDC.SelectObject(&BMP); // 메모리 DC로 BitMap 선택.
MemDC.BitBlt(0, 0, rect.Width(), rect.Height(), &dc, 0, 0, SRCCOPY);
// 현재 화면의 내용을 메모리 DC로 전송한다.
/////////////////////////////////////////////////////////////////////////////////
// 클립보드에 캡춰한 비트맵을 설정한다.
OpenClipboard(); // 현재 클립보드를 연다.
EmptyClipboard(); // 현재 클립보드의 내용을 모두 제거한다.
SetClipboardData(CF_BITMAP, BMP.GetSafeHandle()); // Capture한 비트맵 설정
CloseClipboard();
MemDC.SelectObject(pOldBitmap);
BMP.Detach(); // 비트맵 객체 제거
OpenClipboard();
//클립보드로 카피된게 DIB 형식이 아니면 바로 리턴.
if(!IsClipboardFormatAvailable(CF_DIB))
{
AfxMessageBox("Image file save Fail");
return;
}
hDIB = ::GetClipboardData(CF_DIB);
if(!hDIB)
{
AfxMessageBox("Image file save Fail");
CloseClipboard();
return;
}
CloseClipboard();
//비트맵 헤더의 크기를 계산하고
bifileHdr.bfType = 0x4D42;
bifileHdr.bfSize = sizeof(BITMAPFILEHEADER) + GlobalSize(hDIB);
bifileHdr.bfReserved1 = 0;
bifileHdr.bfReserved2 = 0;
bifileHdr.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
lptrData = (BYTE *)GlobalLock(hDIB);
char szFilter[] = "BMP File(*.bmp)|*.bmp|All Files(*.*)|*.*||";
CFileDialog dlg(FALSE, "bmp", "*.bmp", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter);
if(IDOK == dlg.DoModal())
{
CFile file;
file.Open(dlg.GetPathName(), CFile::modeCreate | CFile::modeWrite);
file.Write(&bifileHdr, sizeof(BITMAPFILEHEADER));
file.Write(lptrData, GlobalSize(hDIB));
file.Close();
}
GlobalUnlock(hDIB);
GlobalFree(hDIB);
참조사이트
http://www.codeguru.com/Cpp/G-M/bitmap/capturing/article.php/c4919/
http://www.codeguru.com/Cpp/G-M/bitmap/capturing/article.php/c4915/
링크는 맨 아래 참고
이 강좌는 리소스에 XML 을 추가하고, 그 리소스를 다시 로드하는 방법에 대해서 설명하였다. 그 중에서 가장 중요한 코드 부분은 다음과 같다.
// Stuff
contents of XML resource into the edit box //
FindResource, LoadResource, LockResource, SizeofResource HRSRC hResource = FindResource(AfxGetResourceHandle(),
MAKEINTRESOURCE(IDR_CUSTOMXML),
_T("XML")
); HGLOBAL hMem = LoadResource(AfxGetResourceHandle(),
hResource); LPCSTR pResource = (LPCSTR) LockResource(hMem); DWORD dwSize = SizeofResource(AfxGetResourceHandle(),
hResource); LPSTR pXMLBuf = new char[dwSize+1]; CopyMemory (pXMLBuf, pResource, dwSize); pXMLBuf[dwSize] = '\0'; CString temp(pXMLBuf); m_editXML.SetWindowText(temp); // Cleanup delete[] pXMLBuf; FreeResource(hMem); |
원본 : http://msdn.microsoft.com/ko-kr/visualc/bb851553(en-us).aspx
for(long i=0; i<10000;
i++) { // do something if( GetAsyncKeyState(VK_ESCAPE) & 0x8000) { MessageBeep(-1); break; } } |
조금만 더 생각해보면 문제를 더 쉽게 해결할 수 있는 방법이 많다.
참고: http://cboard.cprogramming.com/cplusplus-programming/112970-getasynckeystate-key-pressed.html
32비트 윈도우로 넘어오면서 둘다 32비트 값을 가리키게 되었으며, 사실상 Word 와 Long의 구분은 의미 없어 졌으며 예전의 관례가 남아 있는 것이다. 굳이 16 비트 윈도우에서도 작성하는 애플리케이션이 동작해야 한다면 위 구분을 고려해야 하나,
그럴 일은 거의 없을 것이다.
MsgWaitForMultipleObjects and the queue state

One danger of the MsgWaitForMultipleObjects
function is calling it when there are already messages waiting to be processed, because MsgWaitForMultipleObjects
returns only when there is a new event in the queue.
In other words, consider the following scenario:
PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)
returnsTRUE
indicating that there is a message.- Instead of processing the message, you ignore it and call
MsgWaitForMultipleObjects
.
This wait will not return immediately, even though there is a message in the queue. That's because the call to PeekMessage
told you that a message was ready, and you willfully ignored it. The MsgWaitForMultipleObjects
message tells you only when there are new messages; any message that you already knew about doesn't count.
A common variation on this is the following:
MsgWaitForMultipleObjects
returns that there is a message.- You call
PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)
and process that message. - You call
MsgWaitForMultipleObjects
to wait for more messages.
If it so happens that there were two messages in your queue, the MsgWaitForMultipleObjects
does not return immediately, because there are no new messages; there is an old message you willfully ignored, however.
When MsgWaitForMultipleObjects
tells you that there is a message in your message queue, you have to process all of the messages until PeekMessage
returns FALSE
, indicating that there are no more messages.
Note, however, that this sequence is not a problem:
PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)
returnsFALSE
indicating that there is no message.- A message is posted into your queue.
- You call
MsgWaitForMultipleObjects
and include theQS_ALLPOSTMESSAGE
flag.
This wait does return immediately, because the incoming posted message sets the "There is a new message in the queue that nobody knows about" flag, which QS_ALLPOSTMESSAGE
matches and therefore causes MsgWaitForMultipleObjects
to return immediately.
The MsgWaitForMultipleObjectsEx
function lets you pass the MWMO_INPUTAVAILABLE
flag to indicate that it should check for previously-ignored input.
Armed with this knowledge, explain why the observed behavior with the following code is "Sometimes my program gets stuck and reports one fewer record than it should. I have to jiggle // Assume that there is a worker thread that processes records and // posts a WM_NEWRECORD message for each new record. BOOL WaitForNRecords(HANDLE h, UINT cRecordsExpected) { MSG msg; UINT cRecords = 0; while (true) { switch (MsgWaitForMultipleObjects(1, &h, FALSE, INFINITE, QS_ALLINPUT)) { case WAIT_OBJECT_0: DoSomethingWith(h); // event has been signalled break; case WAIT_OBJECT_1: // we have a message - peek and dispatch it if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } if (SendMessage(hwndNotify, WM_GETRECORDCOUNT, 0, 0) >= cRecordsExpected) { return TRUE; // we got enough records } break; default: return FALSE; // unexpected failure } } } ATLINLINE ATLAPI_(BOOL) AtlWaitWithMessageLoop(HANDLE hEvent) { DWORD dwRet; MSG msg; while(1) { dwRet = MsgWaitForMultipleObjects(1, &hEvent, FALSE, INFINITE, QS_ALLINPUT); if (dwRet == WAIT_OBJECT_0) return TRUE; // The event was signaled if (dwRet != WAIT_OBJECT_0 + 1) break; // Something else happened // There is one or more window message available. Dispatch them while(PeekMessage(&msg,0,0,0,PM_NOREMOVE)) { // check for unicode window so we call the appropriate functions BOOL bUnicode = ::IsWindowUnicode(msg.hwnd); BOOL bRet; if (bUnicode) bRet = ::GetMessageW(&msg, NULL, 0, 0); else bRet = ::GetMessageA(&msg, NULL, 0, 0); if (bRet > 0) { ::TranslateMessage(&msg); if (bUnicode) ::DispatchMessageW(&msg); else ::DispatchMessageA(&msg); } if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0) return TRUE; // Event is now signaled. } } return FALSE; }
the mouse to get the value to update. After a while longer, it falls two behind, then three..."
comment :
아래는 Library 에서 사용한 예제 코드
Obtaining Directory Change Notifications

An application can monitor the contents of a directory and its subdirectories by using change notifications. Waiting for a change notification is similar to having a read operation pending against a directory and, if necessary, its subdirectories. When something changes within the directory being watched, the read operation is completed. For example, an application can use these functions to update a directory listing whenever a file name within the monitored directory changes.
An application can specify a set of conditions that trigger a change notification by using the FindFirstChangeNotification function. The conditions include changes to file names, directory names, attributes, file size, time of last write, and security. This function also returns a handle that can be waited on by using the wait functions. If the wait condition is satisfied, FindNextChangeNotification can be used to provide a notification handle to wait on subsequent changes. However, these functions do not indicate the actual change that satisfied the wait condition.
Use FindCloseChangeNotification to close the notification handle.
To retrieve information about the specific change as part of the notification, use the ReadDirectoryChangesW function. This function also enables you to provide a completion routine.
To track changes on a volume, see change journals.
The following example monitors the directory tree for directory name changes. It also monitors a directory for file name changes. The example uses the FindFirstChangeNotification function to create two notification handles and the WaitForMultipleObjects function to wait on the handles. Whenever a directory is created or deleted in the tree, the example should update the entire directory tree. Whenever a file is created or deleted in the directory, the example should refresh the directory.
Note
This simplistic example uses the ExitProcess function for termination and cleanup, but more complex applications should always use proper resource management such as FindCloseChangeNotification where appropriate.
#include <windows.h> void RefreshDirectory(LPTSTR); void _tmain(int argc, TCHAR *argv[]) WatchDirectory(argv[1]); void WatchDirectory(LPTSTR lpDir) _tsplitpath_s(lpDir, lpDrive, 4, NULL, 0, lpFile, _MAX_FNAME, lpExt, _MAX_EXT); lpDrive[2] = (TCHAR)'\\'; // Make a final validation check on our handles. // Change notification is set. Now wait on both notification dwWaitStatus = WaitForMultipleObjects(2, dwChangeHandles, // A time-out occurred. This would happen if some value other default: void RefreshDirectory(LPTSTR lpDir) _tprintf(TEXT("Directory (%s) changed.\n"), lpDir); void RefreshTree(LPTSTR lpDrive) _tprintf(TEXT("Directory tree (%s) changed.\n"), lpDrive); |
From :
MSDN (http://msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx)
Another Reference Sites :
CFileChangeEvent Class (http://www.codeproject.com/KB/files/filechange.aspx)
How to get a notification if change occurs in a specified directory (http://www.codeproject.com/KB/files/DirCheck.aspx)
소멸자를 이용한 테크닉은 어디에서나 활용할 수 있다. 이런 방식을 잊지 말고 활용하자.
class CSimpleLock { public: // Lock CSimpleLock(HANDLE hMutex) { m_hMutext = hMutex; WaitForSingleObject(hMutext, INFINITE); } // Unlock ~CSimpleLock() { ReleaseMutex(m_hMutex); } private: HANDLE m_hMutex; }; |
출처 : Inside COM