PDA

View Full Version : حرفه ای: مشکل در hook کلید F1 جهت نمایش پنجره راهنما



mz6488
جمعه 22 اسفند 1393, 13:39 عصر
سلام.من میخوام تو برنامه م این قابلیت رو بذارم که کاربر با فشردن کلید f1 تو هرجایی از برنامه بتونه از فرم راهنما استفاده کنه.برای همین اومدم کدهای زیر رو تو تایمر صفحه اصلی گذاشتم.مشکل اینجاس که بعضی وقت ها خوب عمل نمیکنه.اصلا نمیشه دیگه جایی کلیک کرد و باید از task manager استفاده کرد.

// ... { GLOBAL HOOK }
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc callback, IntPtr hInstance, uint threadId);


[DllImport("user32.dll")]
static extern bool UnhookWindowsHookEx(IntPtr hInstance);


[DllImport("user32.dll")]
static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, int wParam, IntPtr lParam);

[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);


private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);


const int WH_KEYBOARD_LL = 13; // Номер глобального LowLevel-хука на клавиатуру
const int WM_KEYDOWN = 0x100; // Сообщения нажатия клавиши


private LowLevelKeyboardProc _proc = hookProc;


private static IntPtr hhook = IntPtr.Zero;


public void SetHook()
{
IntPtr hInstance = LoadLibrary("User32");
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, _proc, hInstance, 0);
}


public static void UnHook()
{
UnhookWindowsHookEx(hhook);
}


public static IntPtr hookProc(int code, IntPtr wParam, IntPtr lParam)
{

if (code >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
//////ОБРАБОТКА НАЖАТИЯ
if (vkCode.ToString() == "112")
{
UnHook();
tools.Class1.showForm(tools.Class1._frmLearn, "learn");

}
return (IntPtr)1;
}
else
return CallNextHookEx(hhook, code, (int)wParam, lParam);
}



private void tmrLearn_Tick(object sender, EventArgs e)
{
SetHook();
}

این کدها رو از سایت خارجی گرفتم.کد اسکی کلید f1 رو هم ست کردم.فقط کد هگزا رو که زده 0x100 به جاش 0x70 که مربوط هست به کلید f1 ست کردم ولی جواب نداد واس همین دوباره گذاشتم 0x100

MRasoul
جمعه 22 اسفند 1393, 14:27 عصر
اگر شما میخوای با فشار F1 یه پنجره جدید به عنوان راهنما ظاهر بشه که این کارا براچیه؟خب توی رویداد KeyDown کد بنویس که اگر کلید فشار داده شدهF1 هست، برات پنجره رو ShowDialog کنه

mz6488
جمعه 22 اسفند 1393, 15:47 عصر
اگر شما میخوای با فشار F1 یه پنجره جدید به عنوان راهنما ظاهر بشه که این کارا براچیه؟خب توی رویداد KeyDown کد بنویس که اگر کلید فشار داده شدهF1 هست، برات پنجره رو ShowDialog کنه
خوب من میخوتم این قابلیت تو همه فرم ها باشه.اینکه بیام تو همه فرم ها دونه به دونه دستور رو تو رویداد keyDown بذارم خیلی زمان بره

Mofid.m
جمعه 22 اسفند 1393, 16:14 عصر
خب شما میتونی یه کلاس به پروژت اضافه کنی و از کلاس فرم مشتق کنیش.
بعد بیا کد دوستمونو اونجا بنویس و تمام فرم هاتو از اون مشتق کن.

alibilgats
جمعه 22 اسفند 1393, 16:34 عصر
من از کد زیر استفاده میکنم دوست عزیز.
کافیه فقط توی فرم اصلیتون ازش استفاده کنید. توی کل پروژتون اعمال میشه.

[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
public static extern bool RegisterHotKey(
IntPtr hWnd,
int id,
KeyModifiers fsModifiers,
Keys vk
);
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id );
const int HOTKEY_ID = 31197; //کد منحصر به فرد دلخواه برای تعریف کلید میانبر
public enum KeyModifiers
{
None = 0,
Alt = 1,
Control = 2,
Shift = 4,
Windows = 8
}


public bool setHotKey(KeyModifiers Kmds, Keys key)
{
return RegisterHotKey(this.Handle, HOTKEY_ID, Kmds, key);
}


public bool unSetHotKey()
{
return UnregisterHotKey(this.Handle, HOTKEY_ID);
}


const int WM_HOTKEY = 0x0312;


protected override void WndProc(ref Message message)
{
switch (message.Msg)
{
case WM_HOTKEY:
Keys key = (Keys)(((int)message.LParam >> 16) & 0xFFFF);
KeyModifiers modifier = (KeyModifiers)((int)message.LParam & 0xFFFF);


محل نوشتن کد مربوط به زمان فشرده شدن کلید میانبر


break;
}
base.WndProc(ref message);
}


public Form1()
{
InitializeComponent();


setHotKey(KeyModifiers.None, Keys.F1);

}


البته این نکته رو هم بگم که به نظر من راهنمای برنامه رو شما باید یه فایل دیگه در نظر بگیرید و برنامه اصلی رو درگیرش نکنید.

mz6488
جمعه 22 اسفند 1393, 17:01 عصر
ممنون از شما.یه مشکلی که وجود داره این که فرضا من فرم گزارشات رو باز کردم که به صورت showDialog هستش و فرم راهنما به صورت Show .حالا وقتی وارد فرم گزارشات میشم و کلید f1 رو میزنم فاکوس میره روی فرم گزارشات و روی فرم راهنما نمیشه کلیک کرد و باید فرم گزارشات رو بست.
اینکه فرم آموزش رو گذاشتک تو خود نرم افزار این که کاربر بتونه هر جایی از برنامه بتونه بهش دسترسی داشته باشه

alibilgats
جمعه 22 اسفند 1393, 17:20 عصر
خب دقیقا بخاطر همین من میگم شما فایل راهنما رو یه فایل اجرایی دیگه در نظر بگیرید و کنار فایل اصلی برنامه داشته باشید و با زدن f1 اون فایل رو اجرا کنید. اینطوری فایل راهنما هیچ دخلی به برنامه اصلی نخواهد داشت و تداخلی توی فرم های برنامه ایجاد نمیشه!
فقط کافیه کمی کنترلش کنی! مثلا اینکه چندبار فایل راهنما اجرا نشه! یا اینکه با بستن برنامه اصلی برنامه راهنما هم بسته بشه.

mz6488
جمعه 22 اسفند 1393, 19:29 عصر
خب دقیقا بخاطر همین من میگم شما فایل راهنما رو یه فایل اجرایی دیگه در نظر بگیرید و کنار فایل اصلی برنامه داشته باشید و با زدن f1 اون فایل رو اجرا کنید. اینطوری فایل راهنما هیچ دخلی به برنامه اصلی نخواهد داشت و تداخلی توی فرم های برنامه ایجاد نمیشه!
فقط کافیه کمی کنترلش کنی! مثلا اینکه چندبار فایل راهنما اجرا نشه! یا اینکه با بستن برنامه اصلی برنامه راهنما هم بسته بشه.
حالا اگه کاربر فرم رو minimize کرده بود و بعد دوباره کلید f1 رو بزنه چجوری بیام اون فایل آموزش رو دوباره بازش نکنم و فقط از حالت minimize درش بیارم؟

alibilgats
جمعه 22 اسفند 1393, 22:52 عصر
واسه اینکار شما میتونی با زدن f1 چک کنی که برنامه آموزش درحال اجراست یا نه!
اگه نبود اجراش میکنی و اگر بود یا پیغام میدی که راهنما درحال اجراست یا اینکه روی برنامه فوکوس میکنی. که البته قسمت دومش شاید یکم کار داشته باشه! ولی قسمت اولش رو اگه نداشتی بگو برات کدشو بذارم