안녕하세요?
C# 을 즐겨이 사용하는 전진우라고합니다 ^^
Win32 API를 C#에서 Import 해서 사용하는 방법이 있습니다.
포커싱된 윈도우에 키를 입력하는 함수는 keybd_event 가 있습니다.
제가 간단하게 코드를 한번 적어 볼께요..
-
using System.Runtime.InteropServices;
-
using System.Windows.Forms;
-
-
namespace YourNamespaceHere
-
{
-
class Program
-
{
-
[DllImport("user32.dll")]
-
static extern uint keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
-
-
static void Main(string[] args)
-
{
-
keybd_event((byte)Keys.A, 0, 0, 0); // 'A' key down
-
keybd_event((byte)Keys.A, 0, 0x02, 0); // 'A' key up ( 0x02 = KEYEVENTF_KEYUP )
-
}
-
}
-
}
이정도로 가능하겠습니다.
keydb_event 함수 원형은 아래와 같습니다 (MSDN 참고)
keybd_event
The keybd_event function synthesizes a keystroke. The system can use such a synthesized keystroke to generate a WM_KEYUP or WM_KEYDOWN message. The keyboard driver's interrupt handler calls the keybd_event function.
Windows NT: This function has been superseded. Use SendInput instead.
VOID keybd_event( BYTE bVk, // virtual-key code BYTE bScan, // hardware scan code DWORD dwFlags, // flags specifying various function options DWORD dwExtraInfo // additional data associated with keystroke);
bVk 파라메터에 Keys클래스를 이용해서 키 값을 적어주시면 포커스 된 윈도우에 메시지가 가게 됩니다.
bScan 파라메터는 0으로 두시면됩니다.
dwFlags 파라메터는 0x02 키 업, 0x00 키 다운 입니다.
dwExtraInfo 파라메터는 Shift, Ctrl, Alt키등을 함께 누르게도 할 수 있습니다.
아래는 가상키 와 bVk 파라메터에 넣어주시면 되는 값들을 나열했습니다.
가상키이름 | bVK헥사값 | bVK 파라메터 | |
VK_LBUTTON | 1 | 1 | 마우스 왼쪽 버튼 |
VK_RBUTTON | 2 | 2 | 마우스 오른쪽 버튼 |
VK_CANCEL | 3 | 3 | Ctrl + C |
VK_MBUTTON | 4 | 4 | 마우스 가운데 버튼 |
VK_BACK | 8 | 8 | Backspace |
VK_TAB | 9 | 9 | Tab |
VK_CLEAR | 0C | 12 | CLEAR |
VK_RETURN | 0D | 13 | Enter |
VK_SHIFT | 10 | 16 | Shift |
VK_CONTROL | 11 | 17 | Ctrl(좌측) |
VK_MENU | 12 | 18 | Alt(좌측) |
VK_PAUSE | 13 | 19 | Pause Break |
VK_CAPITAL | 14 | 20 | Caps Lock |
VK_HANGUL | 15 | 21 | 한/영 키 |
VK_HANJA | 19 | 25 | 한자 키 |
VK_ESCAPE | 1B | 27 | ESC |
VK_SPACE | 20 | 32 | Spacebar |
VK_PRIOR | 21 | 33 | Page Up |
VK_NEXT | 22 | 34 | Page Down |
VK_END | 23 | 35 | End |
VK_HOME | 24 | 36 | Home |
VK_LEFT | 25 | 37 | Left Arrow(←) |
VK_UP | 26 | 38 | Up Arrow(↑) |
VK_RIGHT | 27 | 39 | Right Arrow(→) |
VK_DOWN | 28 | 40 | Down Arrow(↓) |
VK_SELECT | 29 | 41 | Select |
VK_EXECUTE | 2B | 43 | EXECUTE |
VK_SNAPSHOT | 2C | 44 | PrtScr |
VK_INSERT | 2D | 45 | Insert |
VK_DELETE | 2E | 46 | Delete |
VK_HELP | 2F | 47 | Help |
VK_0 | 30 | 48 | 0 키 |
VK_1 | 31 | 49 | 1 키 |
VK_2 | 32 | 50 | 2 키 |
VK_3 | 33 | 51 | 3 키 |
VK_4 | 34 | 52 | 4 키 |
VK_5 | 35 | 53 | 5 키 |
VK_6 | 36 | 54 | 6 키 |
VK_7 | 37 | 55 | 7 키 |
VK_8 | 38 | 56 | 8 키 |
VK_9 | 39 | 57 | 9 키 |
VK_A | 41 | 65 | A 키 |
VK_B | 42 | 66 | B 키 |
VK_C | 43 | 67 | C 키 |
VK_D | 44 | 68 | D 키 |
VK_E | 45 | 69 | E 키 |
VK_F | 46 | 70 | F 키 |
VK_G | 47 | 71 | G 키 |
VK_H | 48 | 72 | H 키 |
VK_I | 49 | 73 | I 키 |
VK_J | 4A | 74 | J 키 |
VK_K | 4B | 75 | K 키 |
VK_L | 4C | 76 | L 키 |
VK_M | 4D | 77 | M 키 |
VK_N | 4E | 78 | N 키 |
VK_O | 4F | 79 | O 키 |
VK_P | 50 | 80 | P 키 |
VK_Q | 51 | 81 | Q 키 |
VK_R | 52 | 82 | R 키 |
VK_S | 53 | 83 | S 키 |
VK_T | 54 | 84 | T 키 |
VK_U | 55 | 85 | U 키 |
VK_V | 56 | 86 | V 키 |
VK_W | 57 | 87 | W 키 |
VK_X | 58 | 88 | X 키 |
VK_Y | 59 | 89 | Y 키 |
VK_Z | 5A | 90 | Z 키 |
VK_LWIN | 5B | 91 | 윈도우키(좌측) |
VK_RWIN | 5C | 92 | 윈도우키(우측) |
VK_APPS | 5D | 93 | App Menu 키 |
VK_NUMPAD0 | 60 | 96 | 숫자키패드 0 |
VK_NUMPAD1 | 61 | 97 | 숫자키패드 1 |
VK_NUMPAD2 | 62 | 98 | 숫자키패드 2 |
VK_NUMPAD3 | 63 | 99 | 숫자키패드 3 |
VK_NUMPAD4 | 64 | 100 | 숫자키패드 4 |
VK_NUMPAD5 | 65 | 101 | 숫자키패드 5 |
VK_NUMPAD6 | 66 | 102 | 숫자키패드 6 |
VK_NUMPAD7 | 67 | 103 | 숫자키패드 7 |
VK_NUMPAD8 | 68 | 104 | 숫자키패드 8 |
VK_NUMPAD9 | 69 | 105 | 숫자키패드 9 |
VK_MULTIPLY | 6A | 106 | 숫자키패드 * |
VK_NUMADD | 6B | 107 | 숫자키패드 + |
VK_SEPARATOR | 6C | 108 | SEPARATOR |
VK_SUBTRACT | 6D | 109 | 숫자키패드 - |
VK_DECIMAL | 6E | 110 | 숫자키패드 . |
VK_DEVIDE | 6F | 111 | 숫자키패드 / |
VK_F1 | 70 | 112 | F1 키 |
VK_F2 | 71 | 113 | F2 키 |
VK_F3 | 72 | 114 | F3 키 |
VK_F4 | 73 | 115 | F4 키 |
VK_F5 | 74 | 116 | F5 키 |
VK_F6 | 75 | 117 | F6 키 |
VK_F7 | 76 | 118 | F7 키 |
VK_F8 | 77 | 119 | F8 키 |
VK_F9 | 78 | 120 | F9 키 |
VK_F10 | 79 | 121 | F10 키 |
VK_F11 | 7A | 122 | F11 키 |
VK_F12 | 7B | 123 | F12 키 |
VK_F13 | 7C | 124 | F13 키 |
VK_F14 | 7D | 125 | F14 키 |
VK_F15 | 7E | 126 | F15 키 |
VK_F16 | 7F | 127 | F16 키 |
VK_F17 | 80 | 128 | F17 키 |
VK_F18 | 81 | 129 | F18 키 |
VK_F19 | 82 | 130 | F19 키 |
VK_F20 | 83 | 131 | F20 키 |
VK_F21 | 84 | 132 | F21 키 |
VK_F22 | 85 | 133 | F22 키 |
VK_F23 | 86 | 134 | F23 키 |
VK_F24 | 87 | 135 | F24 키 |
VK_NUMLOCK | 90 | 144 | Num Lock 키 |
VK_SCROLL | 91 | 145 | Scroll Lock 키 |
꼭 성공하시고,
즐거운 프로그래밍 하셔요 ^^
드디어 몇개월동안 고민했던 c# 더블버퍼링 문제 해결!
더블버퍼링 하는 법은 진작부터 알고 있었는데, panel에도 적용시켜줘야 한다는걸 몰랐다.
우리나라 싸이트에는 역시 해답이 없는데
구글에서 c# panel doublebuffering이라고 쳐서 해결
다음은 쓴 소스
public class DoubleBufferPanel : Panel
{
public DoubleBufferPanel()
{
// Set the value of the double-buffering style bits to true.
this.SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint,
true);
this.UpdateStyles();
}
}
이렇게 해준 후에 form1.designer.cs에 가서 panel 부분을 찾아준후 이렇게 바꿔주면 끝
panel1 = new System.Windows.Forms.Panel(); 을
panel1 = new DoubleBufferPanel();
아 기쁘다 내일은 얼른 세부구현 만들어서 넘겨야지!
해결하고 났더니 코딩하고 싶은 마음이 굴뚝같이 생김 ㅋㅋ
출처 : http://cafe.naver.com/winform.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=103
주 제 : BindingNavigator
작 성 자 : 박종명 (mkex)
작 성 일 : 2008년 02월 13일(수)
수 정 일 : 2008년 02월 13일(수)
이번 포스트에서는 비동기 작업을 지원하는 BackgroundWorker 컴포넌트에 대해 알아 보겠습니다.
참고로 구성요소로 번역되는 컴포넌트는 컨트롤과는 달리 UI 를 가지고 있지 않습니다.
아래처럼 Visual Studio 의 도구상자를 통해 폼에 이 컴포넌트를 올리면 폼에 특별한 UI 는 나타나지 않은 채
하위 컴포넌트 목록 창에만 표시됩니다.
뭐.. 중요한 내용은 아니었구요..
비동기 작업이란 수행 시간이 오래 걸리는 작업을 백그라운드 상에서 별도로 처리한게 하는 방법입니다.
즉 메인 쓰레드와 분리된 쓰레드에서 작업을 수행하도록 하여 응용프로그램의 블럭을 방지하고 지연을
최소화하는 프로그래밍 방식입니다.
MSDN에서는 수행시간이 오래 걸리는 작업을 다음처럼 예시하고 있습니다.
이미지 다운로드
웹 서비스 호출
파일 다운로드 및 업로드(피어-투-피어 응용 프로그램에 대한 다운로드 및 업로드 포함)
복잡한 로컬 계산
데이터베이스 트랜잭션
로컬 디스크 액세스(메모리 액세스에 비해 상대적으로 속도가 느림)
그리고 MSDN의 설명 한 마디를 보시죠..
"BackgroundWorker 구성 요소를 사용하면 응용 프로그램의 주 UI 스레드와 다른 스레드에서 시간이 많이 소모되는
작업을 백그라운드"에서 비동기적으로 실행할 수 있습니다"
BackgroundWorker 컴포넌트는 닷넷 2.0 부터 새로이 추가된 컴포넌트 입니다.
물론 이전 버전에서도 사용할 수 있었지만 닷넷 프레임워크에 포함된 형태는 아니었었습니다.
BackgroundWorker 를 사용하기 전에는 이러한 비동기 작업을 처리하기 위해서 수동으로 작업자 쓰레드(Worker Thread)를
직접 생성해서 주 쓰레드(Main Thread) 와 분리하여 작업을 처리하는 코드를 직접 작성했어야 했으며,
작업 진행상황이나 작업 취소와 같은 일련의 작업을 개발자가 직접 해 주어야 했습니다.
쓰레드에 관해서는 다음의 사이트의 글들을 참고 하시기 바랍니다.
[동기화] Interlocked 클래스 와 lock 문
이렇듯 멀티 쓰레드 프로그래밍을 작성할 때는 다양한 이슈가 있습니다.
쓰레드 자체에 대한 자세한 내용은 위의 링크 및 기타 다른 자료로 학습을 하시면 되겠습니다.
이번 글에서는 BackgroundWorker 컴포넌트의 사용방법에 대해서 다루겠습니다.
* BackgroundWorker 의 이벤트
이 컴포넌트를 사용하여 비동기 작업을 하고하 할 경우 알아야 이벤트에 대해서 알아 보겠습니다.
BackgroundWorker 컴포넌트에는 3개의 이벤트가 있습니다.
1) DoWork
백그라운드 작업의 실제 실행을 처리하는 이벤트 입니다.
단 이 이벤트는 자동으로 발생하지 않고 BackgroundWorker 의 RunWorkerAsync 메서드가 호출될 때 발생하게 됩니다.
즉 개발자가 비동기 작업을 위해 RunWorkerAsync 메서드를 호출하면 자동으로 DoWork 이벤트가 발생하게 됩니다.
RunWorkerAsync -> DoWork
2) ProgressChanged
백그라운드 작업의 진행률을 처리하기 위한 이벤트 입니다.
이 이벤트 역시 개발자가 수종으로 발생 시켜줘야 하는데,
BckgroundWorker 의 ReportProgress 메서드를 명시적으로 호출하여 이벤트를 발생시킬 수 있습니다.
또한 연관된 속성으로는 WorkerReportProgress 로써 이 속성이 참(true) 로 설정되어 있어야 됩니다.
ReportProgress -> ProgressChanged
3) RunWorkerCompleted
백그라운드 작업의 완료, 중도 취소, 예외가 생겼을 때 발생하는 이벤트 입니다.
연관된 속성으로는 WorkerSupportsCancellation 로써 이 속성이 참(true) 로 설정되어 있어야 합니다.
이 이벤트의 매개변수인 RunWorkerCompletedEventArgs 객체를 통해 작업이 중도에 취소되었는지, 예외가 발생했는지
를 알 수 있습니다.
이상 3가지 이벤트를 사용하여 손 쉽게 백그라운드 작업을 구현하실 수 있게 됩니다.
* Demo
일단 다음과 같이 오래 걸리는 작업을 수행하는 메서드(DelayMethod)를 작성하도록 합니다.
현재 이 글에서는 이 작업이 무엇을 하는지가 중요한게 아니라 오래 걸리는 작업이 중요한 포인터이기 때문에
실제로 오래걸릴만한 작업이 아닌 의도적으로 중간에 Sleep 를 걸어 두도록 하겠습니다.
다음의 코드가 작업이 오래 걸리는 역할을 하는 메서드 정의입니다.
매개변수로 최대값을 받아서 순차적으로 더해 갑니다. 그리고 최종 더한 값을 반환하도록 합니다.
메서드의 지연처리를 위해 중간에 Thread.Sleep 으로 수행을 잠시 멈춥니다.
(실제로 이런 코드는 있을 수는 없겠죠.. 하지만 테스트를 위해 아래처럼 작성하도록 합니다)
private Int64 DelayMethod(int maxNumber) } return result; |
1. 비동기로 처리 하지 않을 경우
위 메서드를 백그라운드에서 처리하지 않고 동기방식으로 처리하도록 해 보겠습니다.
폼에 버턴을 하나 두고 버턴을 클릭하면 위 메서드가 수행되고 끝나면 결과값을 Label 에 기록하는 간단한 샘플입니다.
버턴이 클릭 되었을 때 다음처럼 메서드를 호출합니다.
Int64 result = DelayMethod(100);
this.lblResult.Text = result.ToString();
최대값을 100 을 주었고 중간중간에 100밀리 세컨드 만큼 수행을 멈추므로 이 작업은 시간이 조금 걸리는 작업이 됩니다.
직접 실행을 해 보면 버턴을 클릭하고 난 후 부터 작업이 완료될 때 까지 폼이 멈춰버리고 다른 어떠한 작업도 할 수 없게 됩니다.
또한 이 폼을 다시 보이게 하려면 다음처럼 하얀색 빈 바탕 화면처럼 나오게 됩니다.
= 원래 폼 모양 =
= 수행 도중 창을 내렸다가 다시 올렸을 경우의 모양 =
시간이 오래 걸리는 작업을 동기로 구현한다면 이러한 문제가 발생합니다.
즉 UI 쓰레드에서 직접 메서드를 수행하기 때문에 다른 곳에서는 제어권을 받을 수 가 없게 되는 것입니다.
2. BackgroundWorker 를 이용해 비동기로 처리하기.
이제 위 메서드를 비 동기로 처리 해 보겠습니다.
우선 폼의 모양을 아래처럼 조금 다듬습니다.
최대값을 사용자로 부터 입력 받기 위한 NumericUpDown 컨트롤과 작업의 시작,취소 버턴
그리고 작업 진행률을 보기 위한 ProgressBar , 결과값 출력을 위한 Lable 컨트롤을 적절히 배치 하였습니다.
이 샘플은 msdn 의 BackgroundWorker 샘플 중 피보나치 수열을 계산하는 샘플을 조금 변형한 것입니다.
① 비 동기 작업의 진행률과 취소를 지원하기 위해 두개의 속성을 설정합니다.
(이 코드에서는 Form_Load 이벤트에서 작성합니다. 디자인 타임에 속성 창을 통해서 하셔도 됩니다)
//최대값 저장을 위한 멤버 변수 int maxNumber = 10;
//폼 로드 이벤트 private void Form1_Load(object sender, EventArgs e) |
② 다음으로 '작업 시작' 버턴을 클릭했을 때 다음 처럼 비동기 작업을 시작하도록 합니다.
private void startAsyncButton_Click(object sender, EventArgs e) //시작된 이후에 필요하지 않은 컨트롤은 사용 불가 처리 한다. this.numericUpDown1.Enabled = false;
// 최대값 얻기
// 진행률 퍼센트 계산을 위한 변수 초기화
//백그라운드 작업을 시작한다.이 메서드 호출은 DoWork 이벤트를 발생시킨다 //이때 매개변수로 최대값을 넘겨 준다 |
③ 이제 본격적으로 BackgroundWorker 컴포넌트의 이벤트를 작성합니다.
= DoWork 이벤트 =
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) //이때 앞서 RunWorkerAsync 메서드 호출 시 전달한 매개변수를 e.Argument 로 다시 넘긴다. //그리고 비동기 작업의 결과 값을 EventArgument 의 Result 에 저장한다. } |
= ProgressChanged 이벤트 =
//BackgroundWorker 의 ReportProgress가 호출될때 발생한다. 비동기 작업 진행률을 보고 받는다 //ProgressBar 에 진행률을 표시한다 |
= RunWorkerCompleted 이벤트 =
//백그라운드 작업이 완료되거나 취소되거나 예외를 발생시켰을 때 발생합니다 |
④ 취소 버턴 클릭 이벤트를 작성합니다
private void cancelAsyncButton_Click(object sender, EventArgs e) //이 메서드 호출로 BackgroundWorker 의 CancellationPending 속성이 true로 설정한다 //취소 버턴 비활성화 |
⑤ 비동기로 수행될 메서드
실제 시간이 오래 걸리는 작업을 하는 메서드 정의 입니다.
기존 비지니스 처리 이외에 BackgroundWorker 의 작업 취소 감지 및 진행률 보고 로직이 포함되어야 합니다
private Int64 DelayMethod(int maxNumber, BackgroundWorker worker, DoWorkEventArgs e)
//진행률을 % 로 계산한다. if (percentComplete > highestPercentageReached)
//ProgressChanged 이벤트를 발생시킨다
//지연을 위해 잠시 멈춘다 //수행을 마치면 결과 값을 반환한다 |
이제 코드 작성이 완료 되었습니다.
첨부파일에 이 글에 사용된 샘플 프로젝트가 등록되어 있으니 다운받으셔서 직접 실행 시켜 보시기 바랍니다.
아래 그림은 프로젝트를 실행완료한 화면 입니다.
이상 닷넷 2.0 에 새로 추가된 BackgroundWorker 컴포넌트에 대해 간략히 살펴 보았습니다.