블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2803)
Unity3D (859)
Programming (479)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (234)
협업 (61)
3DS Max (3)
Game (12)
Utility (140)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (16)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday

Invoke, MethodInvoker, BeginInvoke - EndInvoke

 Introduction

  UI Control들은 폼 구동시 실행되는 하나의 쓰레드에서 구동된다. 따라서 사용자가 실행시킨 쓰레드는 별도로 실행 되기 때문에 이 메인 쓰레드에 적절한 마샬링 없이 다른쓰레드에서 직접 접근하면 다른 쓰레드를 침범하는 것이다. (Cross Thread Problem) 이런 경우에는 프로그램이 개발자가 설계한대로 잘 동작하지 않을 수 있다.(Race Condition,DeadLock)  따라서, 안전하게 동작하게 하기위하여 .Net 환경에서는 Invoke를 제공하고 있다.

 본 내용을 무시한 채 프로그램을 작성하면 InvalidOperationException을 발생시키고 . Debug 창에서 "컨트롤이 자신이 만들어진 스레드가 아닌 스레드에서 액세스되었습니다."라는 메세지가 표시 된다. 하지만 디버깅 환경이 아니라면 프로그램은 겉보기에 정상 동작하는 것 처럼 보일 수 있으므로 조심해야 된다. !

 

난 대충 좀 안되도 상관 없다고 생각하시는 분들은 이 예외를 비활성화 할 수도 있습니다.

 

CheckForIllegalCrossThreadCalls 속성 값을 false로 설정하여 이 예외를 비활성화할 수 있습니다. 그러면 컨트롤이 Visual Studio 2003에서와 같은 방식으로 실행됩니다.

 

이 노트에서 학습하실 때 유념하셔야 될 내용은

  1. Control Invoke 와 Delegate Invoke의 차이점을 숙지한다.
  2. Invoke와 BeginInvoke의 차이점과 사용법을 숙지한다.
  3.  

 자 그럼 쓰레드에서 안전하게 Windows Form control을 제어하게 하는 방법에 대해 알아보자.

우선,  InvokerRequired 를 알고 시작하자.  이 속성은 Invoke메쏘드를 호출해야되는 상황인지 알려준다.

 

Invoke

 

 쓰레드에서 폼 컨트롤 하기 위해서는 별도의(SetTextononTextBox1) 메쏘드를 만들어 사용하면 좋다. 예를들어, Textbox에 값을 입력한다면 아래와 같은 'SetTextonTextBox1' 메쏘드를 만들어서 사용하면 Cross thread 환경이든 내부 쓰레드 사용환경에서든 둘다 사용할 수 있다. 또는 Delegate 메쏘드가 FormControl을 인자로 받아서 사용할 수도 있다.

 Invoke를 사용할 때 인자를 넘겨줘야 하는 메쏘드 필요하면 할때는 반드시 delegate를 선언한 후에 사용하여야 한다.

 

  1.         delegate void SetTextCallback(string txt);                    
            private void SetTextonTextBox1(string txt)
            {
                if (this.textBox1.InvokeRequired)
                {
                    this.Invoke(new SetTextCallback(SetTxtCB), new object[] { txt }); //그냥 txt를 넘겨줘도 된다
                }
                else
                {
                    this.textBox1.Text += txt;
                }
            }
            private void SetTxtCB(string txt)
            {
                this.textBox1.Text+=txt;
            }

 

  1.         public delegate void UpdateText(Control ctrl, string text);
            public void UpdateTextFunc(Control ctrl, string text)
            {
                if (ctrl.InvokeRequired)
                {
                    ctrl.Invoke(new UpdateText(UpdateTextFunc), new object[] { ctrl, text });
                }
                else
                    ctrl.Text += text;
            }

 

인자가 없는 메쏘드를 호출할 때는 간단하게 MethodInvoker를 사용하면 좋다.

 

  1.         private void SetTextonTextBox1(string txt)
            {
                if (this.textBox1.InvokeRequired)
                {
  2.                this.Invoke(new MethodInvoker( delegate { this.textBox1.Text+=txt; }) );

                }
                else
                {
                    this.textBox1.Text += txt;
                }
            }

 

BeginInvoke , EndInvoke

 

 우선 BeginInvoke를 설명하기 전에 Windows Form 의 Control.BeginInvoke 메쏘드와 Delegate.BeginInvoke 메쏘드에 대해서 차이점을 설명하고 본 단락에서는 Winfows Form Control의 BeginInvoke만 설명하도록 하겠다.

 Delegate.BeginInvoke는 Asynchronous Delegate를 만들어서 콜백을 하는 것이라고 생각하면 되겠다. 다시말해서, CLR에서 관리하는 쓰레드풀에서 해당 메쏘드를 큐잉한다. 쉽게 얘기해서 별도의 쓰레드를 만들어서 Delegate를 실행한다고 보면 된다.  장점은 IAsyncResult를 이용해서 Object 결과값을 넘겨 받을 수 있다. 보다 자세한 사항은 이곳을 참조!

  Windows Form의 Control.BeginInvoke는 Control 내부 핸들이 작성된 쓰레드(메인쓰레드)에서 지정된 대리자를 비동기식으로 실행한다. 비동기식이므로 실행을 대기하지 않고 BeginInvoke는 즉시 Return 한다.

 차이점을 정리 하자면 Control.BeginInvoke는 실행코드의 GUI Thread에 작성된 코드이고 Delegate.BeginInvoke는 쓰레드풀 쓰레드에 사용된다. 또한 Control.BeginInvoke의 경우는 EndInvoke를 호출하지 않아도 되나 Delegate.BeginInvoke의 경우는 반드시 Delegate.EndInvoke를 호출해줘야 한다 안그러면 메모리 릭이 발생한다.

 

 

  1. public delegate void InvokeDelegate();
  2. private void Invoke_Click(object sender, EventArgs e)
    {
       myTextBox.BeginInvoke(new InvokeDelegate(InvokeMethod));
    }
    public void InvokeMethod()
    {
       myTextBox.Text = "Executed the given delegate";
    }
  3.  

 

 Endinvoke

 Reference
  1. http://msdn.microsoft.com/ko-kr/library/ms171728.aspx
  2. http://xmlangel.textcube.com/6
  3. http://jongkok4.net/entry/펌c-UI-쓰레드-마샬링-Invoke-BeginInvoke?TSSESSIONjongkok4net=6e5ec00b34c31e0126e9a64412f7a627
  4. http://timl.net/2008/01/begininvoke-methodinvoker-and-anonymous.html
  5. http://shiman.wordpress.com/2008/09/10/c-net-delegates-asynchronous-invocation-begininvoke-method/
  6. http://msdn.microsoft.com/ko-kr/library/0b1bf3y3(VS.80).aspx
  7. http://kristofverbiest.blogspot.com/2007/02/don-confuse-controlbegininvoke-with.html
  8. http://www.albahari.com/threading/#_Introduction
  9. http://www.yoda.arachsys.com/csharp/threadstart.html 




반응형
Posted by blueasa
, |

static const int a;

const static int b;


a와 b가 다른가? 하고 찾아봤는데..


결론은 포인터(*)가 붙지 않는 한 같다. 라는 블로그 포스팅을 발견..


뭔가 내부적으로 다를까.. 했는데..


같구나..


아래는 본문..

---------------------------------------------------------------------------------------

출처 : http://lsrsp.egloos.com/1562353


1. 아래는 모두 같다..
static const int ...
static int const ...
const static int ...
const int static ...
int const static ...
int static const ... 
 
2. 그러나 미테 2개는 다르다..
static const int * foo; // non-constant pointer to a constant variable.
static int * const foo; // constant pointer to a non-constant variable.

반응형
Posted by blueasa
, |

GetWindowRect함수는 화면상의 특정 Window에 대한 위치및 크기를 반환하는 함수입니다.

Declare Function GetWindowRect Lib "user32" Alias "GetWindowRect" (ByVal hwnd As Integer, ByRef lpRect As RECT) As Integer
▶VB.NET 선언

[DllImport("user32")]
public static extern int GetWindowRect(int hwnd, ref RECT lpRect);
▶C# 선언

선언 GetWindowRect함수의 첫번째 인수는 위치및 크기를 얻고자 하는 Window의 Handle을 지정하고 두번째 인수에 실제 위치와 크기에 대한 값이 저장될 구조체를 지정합니다.

여기서 사용되는 구조체는 다음과 같이 선언됩니다.

Public Structure RECT
Public left As Integer
Public top As Integer
Public right As Integer
Public bottom As Integer
End Structure
▶VB.NET

public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
▶C#

만일 실행중인 현재 Form에 대한 위치및 크기값을 가져오려면 GetWindowRect함수를 다음과 같이 선언합니다.

Dim stRect As RECT
GetWindowRect(Me.Handle, stRect)

▶VB.NET 호출

RECT stRect = default(RECT);
GetWindowRect((int)this.Handle, ref stRect);

▶C# 호출



출처 :  http://lab.cliel.com/m/post/view/id/39

반응형
Posted by blueasa
, |

IT, C#, FolderBrowserDialog, C# FolderBrowserDialog, C# 디렉토리, C# OpenFileDialog, OpenFileDialog




How to C# selecting a Directory in an open file dialog
http://ssscripting.wordpress.com/2009/06/07/c-selecting-a-directory-in-an-open-file-dialog/

FolderBrowserDialog dialog = new FolderBrowserDialog();
dialog.SelectedPath  = @"C:\";    // 열 때 폴더를 지정하려면 이런식으로..(추가)

dialog.ShowDialog();
string selected = dialog.SelectedPath;

이렇게 코딩하면 폴더 찾아보기를 구현할 수 있고 선택한 정보는 dialog.SelectedPath 로 넘어오게 되어 폴더 경로 정보를 처리할 수 있습니다.


출처 : http://ndolson.com/1370



[추가] 

폴더 다이얼로그 열릴 때, 시작되는 폴더 위치를 알고싶어서 찾다가

ShowDialog 하기 전에 SelectedPath를 셋팅해주면 된다는 걸 알고 글에 추가해놓음..

근데..

화면 이상 내려가면 스크롤을 내려야 보이는데..

포커스 있는 지점으로 스크롤 이동은 안될려나..

좀 더 알아봐야 될 듯..

반응형
Posted by blueasa
, |

[DllImport("user32.dll")]

static extern IntPtr GetDC(IntPtr hWnd);


[DllImport("user32.dll")]

static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);


[DllImport("gdi32.dll")]

static extern int GetPixel(IntPtr hDC, int x, int y);


//GetPixel()함수 정의, Color객체 반환

static public Color GetPixel(Control control, int x, int y)

{

Color color = Color.Empty;

if (control != null)

{

IntPtr hDC = GetDC(control.Handle);

int colorRef = GetPixel(hDC, x, y);

color = Color.FromArgb(

  (int)(colorRef & 0x000000FF),

  (int)(colorRef & 0x0000FF00) >> 8,

  (int)(colorRef & 0x00FF0000) >> 16);

ReleaseDC(control.Handle, hDC);

}

return color;

}




반응형
Posted by blueasa
, |

using System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Linq;
using
System.Text;
using
System.Windows.Forms;
using
System.Runtime.InteropServices;
using
System.Text.RegularExpressions;


namespace
Color_tool
{
public partial class Form1 : Form
{
   
Regex rgbInputR;
   
Regex rgbInputG;
   
Regex rgbInputB;

   
Match R, G, B;
   
int r;
   
int g;
   
int b;


   
string colorX;

   
[DllImport("gdi32")]
   
private static extern int GetPixel(IntPtr hdc, int x, int y);
   
[DllImport("User32")]
   
private static extern IntPtr GetWindowDC(IntPtr hwnd);

   
private static readonly IntPtr DesktopDC = GetWindowDC(IntPtr.Zero);

   
public static System.Drawing.Color GetPixelAtCursor()
   
{
       
System.Drawing.Point p = Cursor.Position;
       
return System.Drawing.Color.FromArgb(GetPixel(DesktopDC, p.X, p.Y));
   
}

   
public Form1()
   
{
       
InitializeComponent();
   
}

   
private void Form1_Load(object sender, EventArgs e)
   
{
        button1
.BackColor = Color.Black;
   
}

   
private void timer1_Tick(object sender, EventArgs e)
   
{
        colorX
= GetPixelAtCursor().ToString();
       
Color backX = GetPixelAtCursor();
       
this.BackColor = Color.FromArgb(r,g,b);
        label1
.Text = colorX;
        RGB_value
();
   
}

   
private void button1_Click(object sender, EventArgs e)
   
{
       
if (timer1.Enabled == false)
            timer1
.Enabled = true;
       
else
            timer1
.Enabled = false;
   
}

   
private void RGB_value()
   
{
        rgbInputR
= new Regex(@"(?<=R=)\d{0,3}");
        rgbInputG
= new Regex(@"(?<=G=)\d{0,3}");
        rgbInputB
= new Regex(@"(?<=B=)\d{0,3}");

       
Match R, G, B;

        R
= rgbInputR.Match(colorX);
        G
= rgbInputG.Match(colorX);
        B
= rgbInputB.Match(colorX);
       
//had to flip the R and B ???
        b
= int.Parse(R.Groups[0].Value);
        g
= int.Parse(G.Groups[0].Value);
        r
= int.Parse(B.Groups[0].Value);
   
}
 
}
}





반응형
Posted by blueasa
, |

Ogre로 프로젝트를 하면서 가장 시간을 많이 들였던 충돌 처리 부분 입니다. 
처음에는 물리 엔진을 써보고자 Physx , bullet, OgreODE 등 많은 물리엔진을 찾아서 사용 해보려 했지만...;;
결국 Ogre로 구현을 하게 되었습니다. ;; 
게임 개발에 필요한 수학적 지식이 부족한 상황에서 검색을 하던중 directx 로 구현한 OBB 충돌 소스를 찾게 되어서 
그 소스를 이용하여 Ogre에서 구현을 해봤습니다. 

dx 소스는 GpgStudy 에서 참고 하였습니다. 
Link에 추가 해놓으테니까 참고 하시면 좋을 것 같습니다~~
그리고 이만희님의 OBB 충돌 논문(Fast Overlap Test for OBB)
을 보시면 그래도 이해더 좀더 되 실 겁니다.
첨부 파일로 올려 놓겠습니다.(올려도 되려나??)


 
-소스 코드- 

BOOL PlayState::centerOBB(OBBoxRenderable* OBB1, OBBoxRenderable* OBB2)
{

 //box1이 이동하는 OBB / box2는 고정되어 있는 OBB

 Vector3 obb1_center, obb2_center, T, LL; //box1,box2 의 각각 센터 좌표, 
 Real box_len, a1, a2, a3, b1, b2, b3, TL;
 Matrix4 obb1_invers_mat, obb2_rotae_mat;
 Matrix4 R ;

 //OBB 박스의 월드 좌표??
 obb1_invers_mat = OBB1->getCharMat.inverse();
 obb2_rotae_mat = OBB2->getMonMat();

 //box1 의 좌표계를 box2의 좌표계로 회전변환 행렬 R = RA-1 * RB(-1은 iverse)
 R = obb1_invers_mat * obb2_rotae_mat;

 //box의 좌표축의 normal vector x, y, z 값 (제가 이해한 내용 - 틀린 내용 일 수도 있음 ㅋ)

 Vector3 obb1_size = OBB1->getWorldBoundingBox().getSize();
 Vector3 obb2_size = OBB2->getWorldBoundingBox().getSize();

 a1 = obb1_size.x; 
 a2 = obb1_size.y ;
 a3 = obb1_size.z ;

 b1 = obb2_size.x ;
 b2 = obb2_size.y ;
 b3 = obb2_size.z ;

 obb1_center = OBB1->getWorldBoundingBox().getCenter();
 obb2_center = OBB2->getWorldBoundingBox().getCenter();


 //box1 의좌표계에서 box1 중심에서 box2의 중심으로의 이동을 나타내는 vector3
 T = Vector3(obb1_center.x - obb2_center.x, obb1_center.y - obb2_center.y, obb1_center.z - obb2_center.z);

 //0. LL = A1
 box_len = a1 + b1 * R[0][0] + b2*R[0][1] + b3*R[0][2];
 LL =Vector3(1.0f, 0.0f, 0.0f); //분할 축의 벡터 
 TL = T.absDotProduct(LL); //T 와 L의 내적의 절대값
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }
 
 //1. LL = A2
 box_len = a2 + b1 * R[1][0] + b2*R[1][1] + b3*R[1][2];
 LL = Vector3(0.0f, 1.0f, 0.0f);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //2. LL = A3
 box_len = a3 + b1 * R[2][0] + b2*R[2][1] + b3*R[2][2];
 LL = Vector3(0.0f, 0.0f, 1.0f); 
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //3. LL = RB1[R11 R21 R31]
 box_len = a1*R[0][0] + a2 * R[1][0] + a3*R[2][0] + b1;
 LL = Vector3(R[0][0], R[1][0], R[2][0]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //4. LL = RB2[R12 R22 R32]
 box_len = a1*R[0][1] + a2 * R[1][1] + a3*R[2][1] + b2;
 LL = Vector3(R[0][1], R[1][1], R[2][1]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //5. LL = RB3[R13 R23 R33]
 box_len = a1*R[0][2] + a2 * R[1][2] + a3*R[2][2] + b3;
 LL = Vector3(R[0][2], R[1][2], R[2][2]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //6. LL = A1 X RB1 = [1 0 0] X [R13 R23 R33] = [ 0 -R31 R21 ]
 box_len = a2*R[2][0] + a3*R[1][0] + b2*R[0][2] + b3*R[0][1];
 LL = Vector3(0.0f,  R[2][0], R[1][0]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //7. LL = A1 X RB2 = [1 0 0] X [R12 R22 R32] = [ 0 -R32 R22 ]
 box_len = a2*R[2][1] + a3*R[1][1] + b1*R[0][2] + b3*R[0][0];
 LL = Vector3(0.0f,  -R[2][1], R[1][1]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //8. LL = A1 X RB3 = [1 0 0] X [R13 R23 R33] = [ 0 -R33 R23 ]
 box_len = a2*R[2][2] + a3*R[1][2] + b1*R[0][1] + b2*R[0][0];
 LL = Vector3(0.0f,  -R[2][2], R[1][2]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //9. LL = A2 X RB1 = [0 1 0] X [R11 R21 R31] = [R31 0 -R11]
 box_len = a1*R[2][0] + a3*R[0][0] + b2*R[1][2] + b3*R[1][1];
 LL = Vector3(R[2][0], 0.0f, R[0][0]);
 TL = LL.absDotProduct(T);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //10. LL = A2 X RB2 = [0 1 0] X [R12 R22 R32] = [R32 0 -R12]
 box_len = a1*R[2][1] + a3*R[0][1] + b1*R[1][2] + b3*R[1][0];
 LL = Vector3(R[2][1], 0.0f, -R[0][1]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //11. LL = A2 X RB3 = [0 1 0] X [R13 R23 R33] = [R33 0 -R13]
 box_len = a1*R[2][2] + a3*R[0][2] + b1*R[1][1] + b2*R[1][0];
 LL = Vector3(R[2][2], 0.0f, -R[0][2]);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
 /* cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //12. LL = A3 X RB1 = [0 0 1] X [R11 R21 R31] = [-R21 R11 0]
 box_len = a1*R[1][0] + a2*R[0][0] + b2*R[2][2] + b3*R[2][1];
 LL = Vector3(-R[1][0], R[0][0], 0.0f);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //13. LL = A3 X RB2 = [0 0 1] X [R12 R22 R32] = [-R22 R12 0]
 box_len = a1*R[1][1] + a2*R[0][1] + b1*R[2][2] + b3*R[2][0];
 LL = Vector3(-R[1][1], R[0][1], 0.0f);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
  /*cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //14. LL = A3 X RB3 = [0 0 1] X [R13 R23 R33] = [-R23 R13 0]
 box_len = a1*R[1][2] + a2*R[0][2] + b1*R[2][1] + b2*R[2][0];
 LL = Vector3(-R[1][2], R[0][2], 0.0f);
 TL = T.absDotProduct(LL);
 box_len = Math::Abs(box_len);
 if(TL  > box_len)
 {
 /* cout << "충돌되지 않음" << endl;*/
  return 0;
 }

 //cout << "충돌!!" << endl;
 return 1;
}

구현을 해서 실행을 시켜본 결과 충돌 검출은 잘 하는데 살짝 떨어져 있어도 충돌 체크를 하는 경우가 있는데,
이유는 저도 잘...ㅠㅠ 그래도 이렇게해서 충돌 체크를 한다는거에 감사할 따름입니다. ㅋㅋ
혹시 소스 자체에 수정 할 부분이 있다고 생각되시는 분은 가르침 부탁 드리겠습니다^^ㅋ

인증샷!!!!



 Ps. box의 Matrix를 받아 오는 함수를 사용해서 Matrix값을 받아오게 했었는데, 값이 이상 했나 보네여 ;; 충돌 처리가  정확히 되지 않았습니다. 그래서 객체의 Entity 의_getBoneMatrices.transpose()를 사용해서 Matrix값을 받아 와서 충돌처리를 했더니 정확하게 OBB의 충돌 위치에서 멈추는 것을 확인 할 수 있었습니다. 

아직 정확한 Ogre의 분석이 되지 않은 상태에서 이것 저것 해보다가 얻어 걸린 것이라서 정확하게 어떻다라는 것을 제가 말씀 드릴 수는 없을 것 같습니다. 이해해 주시길..^^;; ㅋㅋ

(소스에서 이상한점을 발견 하시거나 잘못 된 곳을 발견하시면 저에게도 살포시 알려주세요~ㅋㅋㅋ)



출처 : http://eguru.co.kr/986

반응형
Posted by blueasa
, |

WPF 속성은 왜이럴까..


창 크기 고정하기 위해서 옵션을 찾아봤지만 별달리 C# 비슷한게 안보여서..


최소/최대 크기를 같게 해줘보니 고정된다..;;





아직은 WPF 초보라..


우선 되는 방법으로 해놔야지..


나중에 다른 좋은방법 찾으면 바꿔야겠다.



[추가]

지나가는 나그네      

xaml 코드에서 ResizeMode="NoResize" 를 추가하시면 간단하게 됩니다.


반응형
Posted by blueasa
, |




WPF로 이리저리 만들고 이벤트를 추가하려고 C#에서 하듯이 '속성-이벤트' 에서 더블클릭을 했는데,


위 창과같은 팝업창이 뜨면서 이벤트 생성이 실패 했다고 떴다.


처음 보는 황당한 에러에 좀 당황하다가..


자세히 읽어보니 [파일의 첫 번째 클래스여야 합니다.] 라는 글귀가 눈에 들어왔다.


간단히 만들어본다고 한 파일에 클래스를 여러개 넣으면서


버릇대로 메인 클래스에 들어갈 클래스를 메인 클래스의 위에 넣었더니 저런 에러가 떠버렸다.


그래서 메인 클래스의 아래로 모든 클래스를 옮겼더니 이벤트 생성이 잘 된다.


WPF는 이런것도 신경 써야되는구나..


(C#도 같은 에러가 나는데 내가 못겪은걸까..? 나중에 테스트 해봐야지..)

반응형

'Programming > WPF' 카테고리의 다른 글

창크기 고정(조절 막기)  (2) 2012.05.22
DispatcherTimer in WPF  (0) 2012.05.21
using 추가해야 될 것 들..  (0) 2012.05.21
WPF 강좌 링크  (0) 2012.03.07
Posted by blueasa
, |

mouse_event (user32)

Programming/C# / 2012. 5. 21. 17:12

Summary
The mouse_event API

C# Signature:

[DllImport("user32.dll")]
static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData,
   UIntPtr dwExtraInfo);

or

[DllImport("user32.dll")]
static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData,
  int dwExtraInfo);

Note that for non-relative mouse movement (i.e. if MOUSEEVENTF_ABSOLUTE is not specified as part of dwFlags), negative values for dx and dy are desirable. As such, the "uint" type specification for C# can be safely replaced with Int32.

User-Defined Types:

  [Flags]
  public enum MouseEventFlags : uint
  {
    LEFTDOWN   = 0x00000002,
    LEFTUP     = 0x00000004,
    MIDDLEDOWN = 0x00000020,
    MIDDLEUP   = 0x00000040,
    MOVE       = 0x00000001,
    ABSOLUTE   = 0x00008000,
    RIGHTDOWN  = 0x00000008,
    RIGHTUP    = 0x00000010,
    WHEEL      = 0x00000800,
    XDOWN      = 0x00000080,
    XUP    = 0x00000100
  }

  //Use the values of this enum for the 'dwData' parameter
  //to specify an X button when using MouseEventFlags.XDOWN or
  //MouseEventFlags.XUP for the dwFlags parameter.
  public enum MouseEventDataXButtons : uint
  {
    XBUTTON1   = 0x00000001,
    XBUTTON2   = 0x00000002
  }

VB.Net Signature:

This function does indeed return a value, just as the keybd_event API does.

If there is a real error, it will in fact return a value of false, or zero.

The dwExtraInfo appears to be a ULONG_PTR in C++ (IntPtr in VB.NET)

Declare Function apimouse_event Lib "user32.dll" Alias "mouse_event" (ByVal dwFlags As Int32, ByVal dX As Int32, ByVal dY As Int32, ByVal cButtons As Int32, ByVal dwExtraInfo As Int32) As Boolean

Notes:

FYI, Microsoft tells us for "Windows NT/2000/XP: This function has been superseded. Use SendInput instead."

The C# code below works fine. However you have to keep in mind to add the namespace "System.Runtime.InteropServices" and keep in mind to write the code into a class.

Original contributor tells us:aa

I wanted to emulate the scroll. Searching for this information wasn't easy ... but here is how you do the mouse scroll button

dim ScrollValue as Integer

ScrollValue = 120 'or -120 for up or down scrolling

mouse_event(&H800, 0, 0, ScrollValue, 0)

Tips & Tricks:

Another contributor tells us:

The scroll value can actually be any value larger than 1, if used within a loop.

This allows you to smoothly increment the scrollbar, instead of relying on the inconsistent wheel delta,

which is a variable limited by the user, for mouse wheel. Start-Control Panel-Mouse-Wheel-Scrolling

VB.NET Sample Code:

    Const MOUSEEVENTF_WHEEL As Int32 = 2048
    Const MOUSEEVENTF_WHEEL_DELTA As Int32 = 120

    Private Declare Function apimouse_event Lib "user32" Alias "mouse_event" (ByVal dwFlags As Int32, ByVal dX As Int32, ByVal dY As Int32, ByVal cButtons As Int32, ByVal dwExtraInfo As Int32) As Boolean
    Private Declare Function apiGetMessageExtraInfo Lib "user32" Alias "GetMessageExtraInfo" () As Int32

    Private Sub PlayScroll(ByVal number As Int32, Optional ByVal increment As Int32 = 2)
    On Error Resume Next
    For i As Int32 = 1 To number
        apimouse_event(MOUSEEVENTF_WHEEL, 0, 0, increment, apiGetMessageExtraInfo)
    Next
    End Sub

C# Sample Code:

    [DllImport("user32.dll")]
    static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);

    [Flags]
    public enum MouseEventFlags
    {
        LEFTDOWN = 0x00000002,
        LEFTUP = 0x00000004,
        MIDDLEDOWN = 0x00000020,
        MIDDLEUP = 0x00000040,
        MOVE = 0x00000001,
        ABSOLUTE = 0x00008000,
        RIGHTDOWN = 0x00000008,
        RIGHTUP = 0x00000010
    }

    public static void LeftClick(int x, int y)
    {
        Cursor.Position = new System.Drawing.Point(x, y);
        mouse_event((int)(MouseEventFlags.LEFTDOWN), 0, 0, 0, 0);
        mouse_event((int)(MouseEventFlags.LEFTUP), 0, 0, 0, 0);
    }

VB.NET 2005 Sample Code:

Based on http://vb-helper.com/howto_move_click_mouse.html

This code assumes a form called frmMain with a command button called cmdClick a picture box called picClicker and a text box called txtResults

Note Twips are no more. Also, I stripped the FOR loop of delta moves from the command button click to the middle of the picture box.

Option Explicit On

Friend Class frmMain

    Inherits System.Windows.Forms.Form

    Declare Auto Sub mouse_event Lib "user32" (ByVal dwFlags As Int32, ByVal dx As Int32, ByVal dy As Int32, ByVal cButtons As Int32, ByVal dwExtraInfo As IntPtr)

    Const MOUSEEVENTF_MOVE As Int32 = &H1 '  mouse move
    Const MOUSEEVENTF_LEFTDOWN As Int32 = &H2 '  left button down
    Const MOUSEEVENTF_LEFTUP As Int32 = &H4 '  left button up
    Const MOUSEEVENTF_RIGHTDOWN As Int32 = &H8 '  right button down
    Const MOUSEEVENTF_RIGHTUP As Int32 = &H10 '  right button up
    Const MOUSEEVENTF_MIDDLEDOWN As Int32 = &H20 '  middle button down
    Const MOUSEEVENTF_MIDDLEUP As Int32 = &H40 '  middle button up
    Const MOUSEEVENTF_ABSOLUTE As Int32 = &H8000 '  absolute move
    Const MOUSEEVENTF_WHEEL As Int32 = &H800 ' wheel button rolled

    ' Simulate moving the mouse to the center of the
    ' PictureBox and clicking.
    Private Sub cmdClick_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles cmdClick.Click
    Dim cur_x As Single
    Dim cur_y As Single
    Dim dest_x As Single
    Dim dest_y As Single

    ' mouse_event moves in a coordinate system where
    ' (0, 0) is in the upper left corner and
    ' (65535,65535) is in the lower right corner.

    ' Get the current mouse coordinates and convert
    ' them into this new system.
    cur_x = System.Windows.Forms.Cursor.Position.X * 65535 / System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width
    cur_y = System.Windows.Forms.Cursor.Position.Y * 65535 / System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height

    ' Convert the coordinates of the center of the
    ' picClicker PictureBox into this new system.
    Dim pt As Point = picClicker.PointToScreen(New Point(picClicker.ClientRectangle.Width / 2, picClicker.ClientRectangle.Height / 2))

    dest_x = pt.X * 65535 / System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width
    dest_y = pt.Y * 65535 / System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height

    txtResults.Text = txtResults.Text & "From " & System.Windows.Forms.Cursor.Position.X & " " & System.Windows.Forms.Cursor.Position.Y & " to " & pt.X & " " & pt.Y & vbCrLf
    txtResults.Text = txtResults.Text & "From " & cur_x & " " & cur_y & " to " & dest_x & " " & dest_y & vbCrLf

    ' Move the mouse to its final destination and click it.
    mouse_event(MOUSEEVENTF_ABSOLUTE + MOUSEEVENTF_MOVE + MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP, dest_x, dest_y, 0, 0)
    End Sub

    Private Sub picClicker_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles picClicker.Click
    txtResults.Text = txtResults.Text & "MouseClick" & vbCrLf
    End Sub

    Private Sub picClicker_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picClicker.MouseDown
    txtResults.Text = txtResults.Text & "MouseDown (" & e.X & ", " & e.Y & ")" & vbCrLf
    End Sub

    Private Sub picClicker_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picClicker.MouseUp
    txtResults.Text = txtResults.Text & "MouseUp (" & e.X & ", " & e.Y & ")" & vbCrLf
    End Sub

End Class

Alternative Managed API:

Per http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/win32map.asp , mouse_event is supposed to be replaced by .NET Framework API System.Windows.Forms.MouseEventArgs but this is not the case. MouseEventArgs is just a data structure w/out event capability. I tried to get:

Dim eMouse As New System.Windows.Forms.MouseEventArgs(Windows.Forms.MouseButtons.Left, 1, pt.X, pt.Y, 0)

Me.OnMouseDown(eMouse)

Me.OnMouseMove(eMouse)

Me.OnMouseUp(eMouse)

to work as desired. Although it did trigger mouse events in the form showing the movement and click action desired, it didn't move the mouse pointer on the screen nor did it trigger events in the picture box located at pt.X, pt.Y

Thus I have resigned myself to unmanaged code for now. I will post the SendInput version shortly as mouse_event has been deprecated by Bill in favor ofSendInput.

As the original contributor noted:

You can use the System.Windows.Forms.Cursor.Position property to set the position of the mouse, if you would like.

You will note I have replaced the GetCursorPos calls in the original VB source with this as suggested in the MSDN URL I mention above.

Documentation
mouse_event on MSDN




반응형
Posted by blueasa
, |