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

카테고리

분류 전체보기 (2797)
Unity3D (853)
Programming (479)
Python (8)
TinyXML (5)
STL (13)
D3D (3)
MFC (1)
C/C++ (54)
C++/CLI (45)
C# (251)
WinForm (6)
WPF (5)
Math (10)
A.I. (1)
Win32API (11)
Algorithm (3)
Design Pattern (7)
UML (1)
MaxScript (1)
FMOD (4)
FX Studio (1)
Lua (2)
Terrain (1)
Shader (3)
boost (2)
Xml (2)
JSON (4)
Etc (11)
Monad (1)
Html5 (4)
Qt (1)
Houdini (0)
Regex (14)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (185)
협업 (61)
3DS Max (3)
Game (12)
Utility (68)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (14)
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

[서론]

  이전에 W.O.W 접속유지 프로그램을 만든적은 있지만 그때는 WOW 캡션이 정해져 있었고, 키입력만으로(방향키를 사용했음) 접속유지가 됐기때문에 단순한 키입력 메시지 전달만 하면 끝이었다. 

  다만.. W.O.W 에서 SendMessage를 먹어버려서 PostMessage로 처리했었다.

  (W.O.W 접속유지 프로그램 링크:http://blueasa.tistory.com/527)


  이번에는 서로(현재는 C# -> C++ 만 되는거 보고 정리함.. 나중에 업뎃 할지도..) SendMessage를 보내서 뭔가 일을 꾸밀(?) 수 있게 해보고 싶은마음에 시작.. 물론 양쪽 프로그램은 내가 직접 만든다는 가정하에..

  세상에 선구자는 많으니 역시나..자료를 찾기 시작.. 이전에 간단하나마 만든 것도 있고..

  말재주는 없으니 본론으로 들어가서 그냥 소스 정리..


[사용된 WinAPI 함수 및 중요 키워드]

FindWindow, SendMessage, WM_COPYDATA


[Send : C#]



[Source]

    public class MessageHelper
    {
        [DllImport("User32.dll")]
        private static extern int RegisterWindowMessage(string lpString);

        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        public static extern Int32 FindWindow(String lpClassName, String lpWindowName);

        //For use with WM_COPYDATA and COPYDATASTRUCT
        [DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = false, EntryPoint = "SendMessage")]
        public static extern int SendMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);

        //For use with WM_COPYDATA and COPYDATASTRUCT
        [DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = false, EntryPoint = "PostMessage")]
        public static extern int PostMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);

        //For use with WM_COPYDATA and COPYDATASTRUCT*
        [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage")]
        private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        [DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage")]
        public static extern int SendMessage(int hWnd, int Msg, int wParam, int lParam);

        [DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "PostMessage")]
        public static extern int PostMessage(int hWnd, int Msg, int wParam, int lParam);

        [DllImport("User32.dll", EntryPoint = "SetForegroundWindow")]
        public static extern bool SetForegroundWindow(int hWnd);

        public const int WM_USER = 0x400;
        public const int WM_SENDER = WM_USER + 4444;
        public const int WM_COPYDATA = 0x4A;

        //Used for WM_COPYDATA for string messages
        //[StructLayout(LayoutKind.Sequential)] 
        public struct COPYDATASTRUCT
        {
            public int dwData;
            public int cbData;
            //[MarshalAs(UnmanagedType.LPStr)]
            public IntPtr lpData;
        }

        public bool BringAppToFront(int hWnd)
        {
            return SetForegroundWindow(hWnd);
        }

        public int SendWindowsStringMessage(int hWnd, int wParam, string command)
        {
            int result = 0;

            if (hWnd != 0)
            {
                byte[] sarr = System.Text.Encoding.Default.GetBytes(command);
                int len = sarr.Length;

                COPYDATASTRUCT cds = new COPYDATASTRUCT();
                //cds.dwData = (IntPtr)100;
                cds.dwData = 0;
                cds.cbData = len + 1;
                //cds.cbData = Marshal.SizeOf(cds);
                cds.lpData = Marshal.StringToHGlobalAnsi(command);
                //cds.lpData = Marshal.StringToCoTaskMemAnsi(command);

                result = SendMessage(hWnd, WM_COPYDATA, wParam, ref cds);
            }

            return result;
        }

        public int SendWindowsMessage(int hWnd, int Msg, int wParam, int lParam)
        {
            int result = 0;

            if (hWnd != 0)
            {
                result = SendMessage(hWnd, Msg, wParam, lParam);
            }

            return result;
        }

        public int GetWindowID(string className, string windowName)
        {
            return FindWindow(className, windowName);
        }
    }





[Use]


int hWnd = messageHelper.GetWindowID(null, windowCaption);
messageHelper.SendWindowsStringMessage(hWnd, 0, String);



[Receive : C++]


[Source]


WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{  
    switch ( msg )   
    {  
    case WM_COPYDATA:  
        {  
            //Used for WM_COPYDATA for string messages  
            struct COPYDATASTRUCT  
            {  
                int dwData;  
                int cbData;  
                PVOID lpData;  
            };  
  
            COPYDATASTRUCT* cp = (COPYDATASTRUCT*)lParam;  
  
            if( NULL != cp )  
            {  
                String strCommand = "";  
                char szCommand[256] = {0,};  
                  
                memcpy( szCommand, cp->lpData, cp->cbData );  
                  
                if(NULL != szCommand)  
                {  
					/// ToDo  
					/// 여기서 받은 문자열로 할 일 하면 됨.  
					/// dwData는 여기선 의미가 없긴한데 enum이나 int 그대로 써서  
					/// switch문 등으로 분기시켜서 여러가지 다양한 처리를 하려고
					/// 처음 소스 짠사람이 만든 것 같다.  
					/// 다른 일도 분류해서 처리하려면 사용하자.  
                }  
            }  
        }  
        break;  
    }  
}  




[주의]

WM_COPYDATA 는 PostMessage로 날릴 수 없다고 한다. SendMessage를 사용하자.

(상대쪽에서 받기 전에 이쪽에서 메모리 해제 되있으면 AV뜨기때문에..)

참고 링크 : http://lunapiece.net/?mid=Tips&listStyle=webzine&document_srl=3780&sort_index=readed_count&order_type=desc


P.s. 마음대로 되지 않고 삽질도 많이해서 여기저기 쓰이지 않는 주석이 남아있긴 하지만.. 삽질기념(?) 그냥 냅두기..

       하도 검색하고 다녀서 참조한 곳을 다 찾기엔 좀 걸리거나 빼먹을 수 도 있을 것 같다. 출처를 찾으러 가야지..



[참조]

http://boycook.wordpress.com/2008/07/29/c-win32-messaging-with-sendmessage-and-wm_copydata/

http://kofmania.tistory.com/45

http://xarfox.tistory.com/45

http://jacking.tistory.com/134

http://www.hoons.kr/board.aspx?Name=qacshap&Mode=2&BoardIdx=10465&Key=&Value=

http://lunapiece.net/?mid=Tips&listStyle=webzine&document_srl=3780&sort_index=readed_count&order_type=desc

- 그 외 못 적은 곳은.. 죄송합니다..;;



반응형
Posted by blueasa
, |

I had a real pain recently where I wanted to control one windows app from another. I found some useful stuff on the net, but nothing that gave an end to end solution. So here’s what I came up with.

Firstly I’ll explain why this is useful. SendMessage is part of the Win32 API, and is used to send messages from one application to another. There are a set of predefined properties that the message can relate to, and these can be used to send messages to existing applications to perform all sorts of useful functions such as changing the font in notepad, or bringing a window to the fore. For more information of the wider use of the SendMessage function, have a look at:

http://www.autohotkey.com/docs/commands/PostMessage.htm

http://msdn.microsoft.com/en-us/library/ms644950(VS.85).aspx

The main use that I’m interested in is passing a specific instruction (via a string) from one app that I’ve written, to another one that I’ve written. This way I can effectively remote control one app from another (particularly useful if you want your main application to open a pop-up, and you don’t want to worry about the pop-up’s performance affecting the main application). Let’s now have a quick look at the SendMessage function:

SendMessage(int hWnd, int Msg, int wParam, int lParam)

hWnd – This is the window instance id of the application you want to send a message to. This id is retrieved using the FindWindow function

Msg – This is the type of message you want to send

wParam – Message specific data you pass in

wParam – Message specific data you pass in

Also used is the FindWindow function. This is to get the relevant window id:

FindWindow(String lpClassName, String lpWindowName)

lpClassName -The name of the class you want

lpWindowName – The name of the window that you want

To send a message that is a string, you need to use the WM_DATACOPY message property. The hard part is that you cannot just send the string as a parameter across. You need to send a pointer to the memory address of the string. If you just want to send an integer as a message you can use the WM_USER message property and send it as a value without a problem.

Below now is a brief listing of my MessageHelper.cs class, for the whole class file see:

http://craigcook.co.uk/samples/MessageHelper.cs.txt

01using System;
02using System.Collections.Generic;
03using System.Linq;
04using System.Text;
05using System.Runtime.Serialization.Formatters.Binary;
06using System.Runtime.InteropServices;
07using System.Diagnostics;
08 
09public class MessageHelper
10{
11[DllImport("User32.dll")]
12private static extern int RegisterWindowMessage(string lpString);
13 
14[DllImport("User32.dll", EntryPoint = "FindWindow")]
15public static extern Int32 FindWindow(String lpClassName, String lpWindowName);
16 
17//For use with WM_COPYDATA and COPYDATASTRUCT
18[DllImport("User32.dll", EntryPoint = "SendMessage")]
19public static extern int SendMessage(int hWnd, int Msg, int wParam, refCOPYDATASTRUCT lParam);
20 
21//For use with WM_COPYDATA and COPYDATASTRUCT
22[DllImport("User32.dll", EntryPoint = "PostMessage")]
23public static extern int PostMessage(int hWnd, int Msg, int wParam, refCOPYDATASTRUCT lParam);
24 
25[DllImport("User32.dll", EntryPoint = "SendMessage")]
26public static extern int SendMessage(int hWnd, int Msg, int wParam, intlParam);
27 
28[DllImport("User32.dll", EntryPoint = "PostMessage")]
29public static extern int PostMessage(int hWnd, int Msg, int wParam, intlParam);
30 
31[DllImport("User32.dll", EntryPoint = "SetForegroundWindow")]
32public static extern bool SetForegroundWindow(int hWnd);
33 
34public const int WM_USER = 0x400;
35public const int WM_COPYDATA = 0x4A;
36 
37//Used for WM_COPYDATA for string messages
38public struct COPYDATASTRUCT
39{
40     public IntPtr dwData;
41     public int cbData;
42     [MarshalAs(UnmanagedType.LPStr)]
43     public string lpData;
44}
45 
46public bool bringAppToFront(int hWnd)
47{
48     return SetForegroundWindow(hWnd);
49}
50 
51public int sendWindowsStringMessage(int hWnd, int wParam, string msg)
52{
53    int result = 0;
54 
55     if (hWnd != 0)
56     {
57            byte[] sarr = System.Text.Encoding.Default.GetBytes(msg);
58            int len = sarr.Length;
59            COPYDATASTRUCT cds;
60            cds.dwData = (IntPtr)100;
61            cds.lpData = msg;
62            cds.cbData = len + 1;
63            result = SendMessage(hWnd, WM_COPYDATA, wParam, ref cds);
64     }
65 
66     return result;
67}
68 
69public int sendWindowsMessage(int hWnd, int Msg, int wParam, int lParam)
70{
71     int result = 0;
72 
73     if (hWnd != 0)
74     {
75            result = SendMessage(hWnd, Msg, wParam, lParam);
76     }
77 
78     return result;
79}
80 
81public int getWindowId(string className, string windowName)
82{
83 
84     return FindWindow(className, windowName);
85 
86}
87}

So now you can call the code to send a message like so:

MessageHelper msg = new MessageHelper();
int result = 0;
//First param can be null
int hWnd = msg.getWindowId(null, “My App Name”);
result = msg.sendWindowsStringMessage(hWnd, 0, “Some_String_Message”);
//Or for an integer message
result = msg.sendWindowsMessage(hWnd, MessageHelper.WM_USER, 123, 456);

Now all you need to do on the app that you want to receive the message is override the following function in the form class (obviously you can change what the responses are, and you’ll need to create constants for the parameters):

01protected override void WndProc(ref Message m)
02{
03switch (m.Msg)
04{
05     case WM_USER:
06            MessageBox.Show("Message recieved: " + m.WParam + " - " + m.LParam);
07            break;
08     case WM_COPYDATA:
09            COPYDATASTRUCT mystr = new COPYDATASTRUCT();
10            Type mytype = mystr.GetType();
11            mystr = (COPYDATASTRUCT)m.GetLParam(mytype);
12            this.doSomethingWithMessage(mystr.lpData);
13            break;
14}
15base.WndProc(ref m);
16}


출처 : http://boycook.wordpress.com/2008/07/29/c-win32-messaging-with-sendmessage-and-wm_copydata/

반응형
Posted by blueasa
, |

Spy++의 창 핸들을 찾는 방식을 어떻게 구현하나 뒤지다가 C++ 로 코드프로젝트에 만들어져 있는걸 보고,


C# 으로 만들어진 게 없나 하고 찾아봤는데..


역시나 있다..


만쉐~ 역시 선구자들은 많아.. 잘사용해보세~ -_-;


링크 : http://devpia.co.kr/MAEUL/Contents/Detail.aspx?BoardID=50&MAEULNO=20&no=881823&ref=881821&page=1


C++ 소스 링크 : http://www.codeproject.com/Articles/1698/MS-Spy-style-Window-Finder


C# 소스 링크 : http://www.codeproject.com/Articles/34981/FindWindow

반응형
Posted by blueasa
, |


MouseKeyboardLib2008.zip



원문 : http://www.codeproject.com/KB/system/globalmousekeyboardlib.aspx

물론 그냥 쌩으로 만들어 써도 되지만 , 이렇게 잘 정리되고 간단한 라이브러리를 쓰는것도 참 괜찮은 방법.

예제는 프로젝트를 열어보면 있다.

간단한 키보드 후킹 사용법 : 

            KeyboardSimulator.KeyDown(System.Windows.Forms.Keys.A);
            KeyboardSimulator.KeyUp(System.Windows.Forms.Keys.A);

유의점이라면 매개변수 'Keys' 는 윈폼의 것이다. 따라서 참조에 윈폼을 추가해야 한다.
그냥 WPF 로 바꿔도 무방하다만, WPF 만 할것도 아니고 XNA 도 있고 여러가지 상황을 생각한다면 
걍.. 이대로 쓰는것도 그리 불편하진 않다.

반응형
Posted by blueasa
, |






EventArgs 를 상속받는 클래스 안에다가 이벤트에 필요한 "event" 와 delegate  를 함께 작성 함으로서 구현 코드의 코드량을 줄였다.



이벤트 클래스 작성
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace StikusFrameAuth.events
{
    public class SFATraceEvent : EventArgs
    {
        //event
        public delegate void SFATraceEventDele(object sender, SFATraceEvent e);
        public static event SFATraceEventDele TraceEvent;


        //arg
        public STATUS_TYPE statusType { get; private set; }
        public string contentString { get; private set; } 
        public SFATraceEvent(STATUS_TYPE _statusType , params object[] _content)
            : base()
        {
            statusType = _statusType;
            foreach (var s in _content)
            {
                contentString += s.ToString() + " ";
            }
        }
        public enum STATUS_TYPE
        {
            COMMENT
        }


        //dispatch
        public static void dispatchEvent(object sender,  params object[] _content)
        {
            TraceEvent(sender, new SFATraceEvent(STATUS_TYPE.COMMENT, _content));
        }
    }
}



구현
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using StikusFrameAuth.events;
namespace StikusFrameAuth
{
    public class StikusFrameAuth
    {
        public StikusFrameAuth()
        {

            //addEventListener
            SFATraceEvent.TraceEvent +=new SFATraceEvent.SFATraceEventDele(SFATraceEventArg_SFATraceEvent);
            


            //dispatchEvent
            SFATraceEvent.dispatchEvent(this,  "argString" , "wow");
        }

        void SFATraceEventArg_SFATraceEvent(object sender, SFATraceEvent e)
        {
            Console.WriteLine(e.contentString);
        }
    }
}


AS3 의 addEventlistener , DispatchEvent 와 엇비슷한 형태로 사용이 가능하다

반응형
Posted by blueasa
, |

Dictionary foreach

Programming/C# / 2012. 4. 25. 12:04

KeyValuePair 를 이용한다


            Dictionary<String, Object> dic = new Dictionary<String, object>();
            dic.Add("String0", true);
            dic.Add("String1", 13);

            foreach (KeyValuePair<String, Object> p in dic)
            {
                Console.WriteLine(p);
            }




반응형
Posted by blueasa
, |
간단한 팁 하나 알려드릴께요. 

솔루션 폴더에 보시면 

Properties 라는게 보이실꺼예요 
여기에 Settings 라는거 클릭하시고 키를 하나 만드시고 타입을 int 로 하시공 -1 값 지정후 Ctrl + S로 저장 하세요.

다음 form에 Shown이벤트 처리를 추가하시공,  

ComboBox.SelectedIndex = Settings.Default.{추가한 키(프로퍼티가 보이실꺼예요.)};


form닫히는 Close 이벤트에서 

Settings.Default.{추가한 키(프로퍼티가 보이실꺼예요.)} = ComboBox.SelectedIndex; Settings.Default.Save(); 

- 끝 - 쉽죵? 


P.s. 우오오~!! 이런 간단한 방법이..!! 이런식으로 사용하는 거였다니!! =ㅁ=!

출처 :   http://hoons.kr/Board.aspx?Name=QACSHAP&Mode=2&BoardIdx=48049&Key=&Value=  의 [퇴근5분전]님 리플
반응형
Posted by blueasa
, |
이번 예제는 openFileDialog를 활용하여 파일 첨부 기반을 만드는 방법을 소개하도록 하겠습니다.
이 강좌는 파일 처리 기능은 구현하지 않았습니다. 이유는 openFileDialog를 활용하는 것이 핵심 키워드이기 때문입니다.
이점을 인지하고 읽어주시기 바랍니다.
한 가지 더 말씀드리자면, openFileDialog를 활용하는 예제이기에 파일 제약 조건에 관하여 언급하였습니다.

1. 폼 인터페이스 디자인



TextBox, Button, openFileDialog를 적절히 배치해주시기 바랍니다.

2. 소스 코드

Button을 더블 클릭하시어 소스코드를 불러오시고 입력하시기 바랍니다.


        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFile = new OpenFileDialog();
            openFile.DefaultExt = "jpg";
            openFile.Filter = "Images Files(*.jpg; *.jpeg; *.gif; *.bmp; *.png)|*.jpg;*.jpeg;*.gif;*.bmp;*.png";
            openFile.ShowDialog();
            if (openFile.FileNames.Length > 0)
            {
                foreach (string filename in openFile.FileNames)
                {
                    this.textBox1.Text = filename;
                }
            }
        }

openFile.DefaultExt = "기본확장자";
openFile.Filter = "항목이름정의1|확장자1;확장자2;  … 확장자n;|   … 항목이름정의n|확장자1;확장자2;  … 확장자n;";
openFile.ShowDialog();  -> 파일 열기 창 호출



3. 동작 과정




4. 자세히 이해하고 싶다면

소스에 있는 속성들을 측정해보시기 바랍니다.

5. 소스 코드 첨부

 


반응형
Posted by blueasa
, |

오디오 재생을 위해
.net framework에 기본으로 포함되어 있는
System.Media.SoundPlayer를 사용중 몇가지 문제점을 발견하여
대체할 수 있는 놈들을 아래와 같이 조사해 보았습니다.
최종적으로는 오픈소스인 NAudio 를 선택하였구요..
써보니.. 좋네요.. ^^

1. DirectX

   - http://www.alvas.net/alvas.audio.aspx 
   - Microsoft.DirectX.AudioVideoPlayback.dll 을 참조추가
   - .net 1.x기준으로 만들어진듯함. 2.0~3.5에서는 초기 로딩시 Loader Lock Exception 발생
   - Loader Lock 예외처리 : http://hanury.net/wp/archives/549  
   - .net 4.0에서는 실행안됨

2. System.Media.SoundPlayer

   - 동시에 여러개의 사운드를 재생할 수 없음
   - A가 재생중, B를 멈추면 A도 멈춤
   - 사용이 쉬움
   - Stream 사용이 가능하여 음원을 Resource에 넣어서 배포 가능
   - .wav 파일만 지원함
   

3. Alvas.Net

   - 상용
   - http://www.alvas.net/alvas.audio.aspx 
   - 기능 : Records audio, Plays audio, Set up mixer controls, Edits audio, Converts audio


4. NAudio

   - 무료, 오픈소스
   - http://naudio.codeplex.com/ 
   - Play back audio, Decompress audio, Record audio, Mix and manipulate audio streams 등..
   - Stream 사용가능, wav 및 mp3 사용가능


반응형
Posted by blueasa
, |
간단하게 결론..

Dll 파일을 찾을 수 없어서 나는 에러..

프로그램이 Dll 파일을 찾을 수 있는 곳에 넣어줘야 된다.


추가 : 디버깅 시,
         해당 프로젝트가 찾을 수 있게 넣어줘도 에러가 나서 난리쳤다.
         삽질 결과 해당 프로젝트가 아니라,
         해당 솔루션의 기본 실행 프로젝트가 참조 할 수 있게 해줘야 된다.


반응형
Posted by blueasa
, |