Click here to Skip to main content
15,881,881 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi everyone

I want to create an application using Hook, will run in background, when I press a button (f.e. F12), program draws on the display "F12 is pressed" on screen. I want to drawing s string over other fullscreen apps (games...) like that http://i1176.photobucket.com/albums/x331/DuyBK283/fraps.jpg[^]

Instead of numbers 122 I want to draw "F12 is pressed". How can i do that ?

PS: Sorry for my bad english
Posted
Updated 18-Nov-11 10:28am
v2
Comments
Sergey Alexandrovich Kryukov 18-Nov-11 18:54pm    
Why do you think you need a hook for this?
--SA
pham.quocduy 18-Nov-11 20:39pm    
The main thing I want to do is draw a string on screen. Hook is the only means, this will indicate when to draw

First of all, create a new class library in the Visual Studio. This is a .net remoting example.

C#
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.IO;

namespace MyRemotingLibrary
{
    public interface IHttpRemoting
    {
        string SendPressedKey(string key);
    }
    
    public class MyHttpRemoting : MarshalByRefObject, IHttpRemoting
    {
        public string SendPressedKey(string key)
        {
            string path = @"c:\KeyTable.txt";
            StreamWriter writer = new StreamWriter(path);
            writer.WriteLine(key);
            writer.Close();
            return key;
        }
    }
}


And then, create a new server application for sending pressed keys from the client to the server application. (Client may be a classic .net application, a notepad or internet browser running on your machine.)

Create a new Windows Form application and add a Timer component and a TextBox control on your design form. ( And don't forget to reference System.Runtime.Remoting and our created remoting library to your project.)

C#
using System.IO
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using MyRemotingLibrary;

namespace ServerApplication
{
    public partial class Form1 : Form
    {
        private void Form1_Load(object sender, EventArgs e)
        {
            textBox1.Multiline = true;
            /* ... */
            HttpChannel channelHttp = new HttpChannel(8000);
            ChannelServices.RegisterChannel(channelHttp);
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(MyHttpRemoting), "MyKeyPressedWebService", WellKnownObjectMode.SingleCall);
            /* ... */
            timer1.Interval = 10; // Ten milliseconds.
            timer1.Start();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            string path = @"c:\KeyTable.txt";
            try
            {
                FileInfo fInfo = new FileInfo(path);
                if(fInfo.Exists)
                {
                    StreamReader reader = new StreamReader(path)
                    string newLineString = reader.ReadLine();
                    textBox1.Text += newLineString;
                    reader.Close();
                    /* ... */
                    fInfo.Delete();
                }
            }
            catch {;}
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            string path = @"c:\KeyTable.txt";
            FileInfo fInfo = new FileInfo(path);
            if(fInfo.Exists)
            {
                fInfo.Delete(); // Delete the created file when we're closing the server application.
            }
        }
    }
}


And finally create a new client application for handling pressed keys. After than, this application sends pressed keys to our side. (This is a main application for us.)

1. Create a new Windows Form application.
2. Reference to System.Runtime.Remoting and our created library to our client project.
3. Add a new TextBox and two timer component to your design form.

C#
using System;
using System.Windows.Forms;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.InteropServices;
using System.IO;
using MyRemotingLibrary;

namespace ClientApplication
{
    public partial class Form1 : Form
    {
        /* API Declarations */
        [DllImport("User32")]
        private static extern short GetAsyncKeyState(Int32 value);
        
        [DllImport("User32")]
        private static extern short GetAsyncKeyState(System.Windows.Forms.Keys virtualKeys);
        
        string strOne, strTwo;

        public delegate string Trigger(string key);
        TcpChannel channelTcp;
        Trigger InvokeMethod;

        private void Form1_Load(object sender, EventArgs e)
        {
            timer1.Interval = 1;
            timer2.Interval = 2;
            timer1.Enabled = true;
            timer2.Enabled = true;
            textBox1.MaxLength = 1; // Maximum one character.
            strOne = String.Empty;
            /* ... */
            channelTcp = new TcpChannel();
            ChannelServices.RegisterChannel(channelTcp);
            IHttpRemoting remoteService = (IHttpRemoting)Activator.GetObject(typeof(IHttpRemoting), "http://localhost:8000/MyKeyPressedWebService");
            /* ... */
            InvokeMethod = new Trigger(remoteService.SendPressedKey);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            foreach(int current in Enum.GetValues(typeof(Keys)))
            {
                if(GetAsyncKeyState(current) == -32767)
                {
                    strOne += Enum.GetName(typeof(Keys), current) + " ";
                }
            }

            strTwo = null; // Clear it.
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            try
            {
                strTwo = strOne;
                if(strTwo.Length <= 3)
                {
                    textBox1.Text = strOne;
                }
                strOne = null;
            }
            catch {;}
        }
        
        /* TextChanged event for TextBox control. */
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            string key = textBox1.Text;
            InvokeMethod(key);
        }
    }
}


Test it, in your client application or write some text in a editor(Notepad like), or enter a text in the google search bar and then look at your server application something that happen.
 
Share this answer
 
Comments
[no name] 18-Nov-11 22:46pm    
This has nothing to do with the OPs question
Burak Ozdiken 18-Nov-11 23:02pm    
How do you capture the pressed key?

duybk283 says that; I want to create an application using Hook, will run in background. Maybe this application will be inactive. In this case, you can not handle a key from your application. The main idea, first of all handle a virtual key and after draw a string on a application.
pham.quocduy 19-Nov-11 7:40am    
This isn't what I think. Hook is the only means, this will indicate when to call drawing.
How to use hook I have finished. I just want to know, "How to draw a string on screen over other apps"
Burak Ozdiken 19-Nov-11 9:08am    
maybe this link can help you.

http://www.codeproject.com/KB/cs/OSDwindow.aspx
pham.quocduy 19-Nov-11 10:51am    
Thank for your link !
I've tested it. Unfortunately it was not what I wanted :(
Although the text is displayed in desktop, but when I run a game, the text not displaying over the screen of game :(
I found a sample application, you can download it from this links;

https://skydrive.live.com/?cid=da49be3d7591a40a&sc=documents&id=DA49BE3D7591A40A!156 ( Fraps like Sample Application.)

http://slimdx.org/download.php (Library project.)

and you can find articles in here;

http://spazzarama.wordpress.com/2009/02/07/screencapture-with-direct3d/

http://www.ring3circus.com/gameprogramming/direct3d-9-hook-v11/
 
Share this answer
 
Comments
pham.quocduy 21-Nov-11 10:43am    
There are examples to capture screen with Direct library. Any sample application like Fraps isn't here :(
Burak Ozdiken 21-Nov-11 11:16am    
Not only capture screen, if you look at the code samples not articles, you can find something useful for you. If you want to draw a string on a direct-x game, you need to use the direct-x library for your projects. You can not achieve this using the others. ( GDI, GDI+ etc. )
Although you get the handle of a window, including the desktop, I don't believe this will work. The other application will just paint over your message the next to a wm_paint message is processed. For a game, the screen is refreshed quite often
 
Share this answer
 
Comments
pham.quocduy 19-Nov-11 7:46am    
One such application is called Fraps
Is there a similar program in C# ? :\
[no name] 20-Nov-11 21:10pm    
I don't see where this is doing what you are looking for. There is a difference between DirectX and OpenGL games and normal Windows applications. Good luck

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900