PDA

View Full Version : سوال: مشكل در توابع api و Sendkey و كپي كردن در كليپ بورد و پيست نمودن آن در برنامه ديگه



rezankh
جمعه 03 بهمن 1393, 00:55 صبح
با سلام
برنامه‌اي دارم كه داراي چندين تسكت باكس و كمبوباكس و باتن هست كه مي‌بايست اطلاعات زيادي رو بصورت تكراري درونش وارد كنم. لذا تصميم گرفتم با استفاده از توابع API هندل فرم رو پيدا كنم و سپس هندل كنترلها كه در اين كار موفق نبودم دو سه روزه كه تموم اينترنت و سايت (با عض پوزش از ايجاد تاپيك جديد) رو جستجو كردم كه تقريبا متوجه شدم توي ويندوز سون با تابع FindWindowEx بدلايلي بعضي اوقات كار نميكنه(شك دارم، نمي دونم). دست آخر تصميم گرفتم بجاي بدست آوردن هندل تكست باكس‌ها از سورس زير استفاده كردم و يك نمونه از برنامه مورد نظر (فرمي با چند كنترل مختلف) رو جهت تست و بررسي و اصلاح اينجا ميزارم لطفا دوستان بررسي كنند آخه خيلي فوريه. ممنون

Saman_12
جمعه 03 بهمن 1393, 01:16 صبح
این اطلاعات از کجا میان؟ برنامه مورد نظر رو خودتون نوشتید؟
توضیح کافی و صریح بدید

rezankh
جمعه 03 بهمن 1393, 02:09 صبح
جهت ازسال اطلاعات به يك برنامه ديگه ابتدا از توابع api براي هندل كردن و سپس ارسال استفاده كردم كه موفق نشدم هندل كنترل‌هاي روي فرم بدست بيارم. سپس از كپي كردن متن از فرم خودم و سپس sendkeys نمودن به برنامه مورد نظر استفاده كردم ولي مشكلم اينه كه زماني كه مقدار باكس دوم رو از فرم ويژوال خودم كپي ميگيرم، مقدارش در باكس‌هاي ديگه برنامه هم پيست ميشه ( اگه برنامه رو اجرا كنيد متوجه منظورم ميشيد. ( باتن 2 رو بررسي كنيد. در ضمن فايل exe برنامه تست هم داخل پوشه هست.) در ضمن چون در حال تست هاي مختلف بودم كدها رو خودم نوشتم(با استفاده از اينترنت). ممنون

Saman_12
جمعه 03 بهمن 1393, 10:04 صبح
برنامه تون رو دیدم تقریبا هم متوجه ام که چیکار میخوایید بکنید ولی نگفتید هر دو برنامه رو خودتون مینویسید یا نه (اگر بخوایید اطلاعاتی رو بین دو برنامه که خودتون نوشتید منتقل کنید راه های خیلی ساده تری مثل لوله یا حتی استفاده از فایل ها و .. وجود دراه.) :

برای استفاده از FindWindow و FindWindowEx باید نام کلاس و کپشن شی مورد نظر رو بدونید که الزاما این نامی که استفاده میکنید نیست ("calssname<>button").

-از منوی tools ویژوال استدیو برنامه spy++ رو اجرا کنید و با استفاده از Alt+F3 سرچ ویندو رو باز کنید آیکون روبه روی Finder tool رو با موس نگهدارید و روی کنترل یا پنجره مورد نظر بکشید حالا کلاس و کپشن رو یاداشت کنید و از اونها استفاده کنید(مثلا برای تکست باکس شما کلاس WindowsForms10.EDIT.app.0.378734a هست.)

اگر در استفاده از هرکدوم از توابع مشکلی داشتید مطرح کنید.(فقط کلی نگید ذکر کنید کجا مشکل دارید.)

rezankh
جمعه 03 بهمن 1393, 10:51 صبح
با برنامه spy++ هم كار كردم ولي هندل كنترل ها رو بعضي اوقات عدد و بعضي اوقات رشته نشون ميده كه اين با تابع sendmessage كه هندل كنترل رو بصورت int و يا intptr دريافت ميكنه جواب نميده و زماني كه سعي ميكنم از sendmessage براي ارسال مقدار به كنترلها استفاده كنم اتفاقي نمي افته. ضمن اينكه برنامه هدف در واقع يك نرم‌افزار حسابداري هست و فقط براي تست من خودم يك اپليكيشن جدا نوشتم كه براي شما هم توي پوشه گذاشتم. اگه ميشه خودتون روي همين سورس كدش رو بنويسيد و امتحان كنيد. شايد من اشتباه كرده باشم.

Saman_12
جمعه 03 بهمن 1393, 14:17 عصر
ببینید مثل اینکه دچار سوبرداشت از توابع و همینطور هندل شدید :

-هندل همیشگی و پایدار نیست که شما بخواید به عنوان یک مشخصه یکتا برای تمام زمان ها ازش استفاده کنید بلکه وقتی شی ساخته میشه سیستم یک هندل خاص به اون اختصاص میده و بعد از ازبین رفتن شی بتبع هندل هم بسته میشه.
-شما باید با استفاده از نام کلاس و کپشن پنجره مورد نظزتون رو پیدا کنید و هندل اون رو بگیرید (خروجی تابع FindWindow) و با استفاده از هندل پنجره که بدست میارید برای اون پیام بفرستین.

یه مثال برای پیدا کردن پنجره های نوتپد باز سیستم تون میزنم :


[DllImport("user32.dll")]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);


[DllImport("user32.dll")]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);


[DllImport("user32.dll", EntryPoint = "GetWindowTextA")]
private static extern bool GetWindowText(IntPtr hWnd, StringBuilder prmstrString, Int32 nMaxCount);



List<IntPtr> hwndlist = new List<IntPtr>();
IntPtr np_hwnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Notepad", null);


while (np_hwnd != IntPtr.Zero)
{
hwndlist.Add(np_hwnd);
np_hwnd = FindWindowEx(IntPtr.Zero, np_hwnd, "Notepad", null);
}


List<string> Captionlist = new List<String>();


foreach (IntPtr h in hwndlist)
{


StringBuilder cap_str = new StringBuilder();


cap_str.Length = 256;

bool gwt_result = GetWindowText(h, cap_str, cap_str.Length);
if (gwt_result) { Captionlist.Add(cap_str.ToString()); Console.WriteLine(cap_str.ToString()); }
}

rezankh
جمعه 03 بهمن 1393, 16:40 عصر
ببینید مثل اینکه دچار سوبرداشت از توابع و همینطور هندل شدید :

-هندل همیشگی و پایدار نیست که شما بخواید به عنوان یک مشخصه یکتا برای تمام زمان ها ازش استفاده کنید بلکه وقتی شی ساخته میشه سیستم یک هندل خاص به اون اختصاص میده و بعد از ازبین رفتن شی بتبع هندل هم بسته میشه.
-شما باید با استفاده از نام کلاس و کپشن پنجره مورد نظزتون رو پیدا کنید و هندل اون رو بگیرید (خروجی تابع FindWindow) و با استفاده از هندل پنجره که بدست میارید برای اون پیام بفرستین.

من توي سورسي گذاشتم مي‌بينيد كه بايد هندلي كه از پنجره باز شده گرفته ميشه رو داخل تكست باكس دستي وارد نمود در غير اينصورت اطلاعات ارسال نميشه و اينكه هندل يك چيز متغيير هست رو كاملا ميدونم. و نيز مثالي كه با نوت پد گذاشتيد رو هم توي باتن 3 كار كردم و نيز كار با 3 تابع فوق رو. منتها چون نتونستم با تابع FindWindowEx هندل كنترلهاي داخل پنجره رو بدست بيارم متوسل به يك كار پيچيده تر شدم . بهر حال اگه ميشه يك توضيحي نسبت به كدهاي قسمت دوم خودتون بديد و نيز اگه ميشه همين و با برنامه تست Program Test ( موجود در داخل پوشه) انجام بديد.

Saman_12
شنبه 04 بهمن 1393, 00:12 صبح
احتمالا چندوقت آنلاین نمیشم از بقیه دوستان بخواید کمکتون کنند.
این هم یه نمونه دیگه توضیح هم روش هست :

//define function and const that we need
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, Int32 msg, IntPtr wParam, string lParam);




private const Int32 WM_SETTEXT = 0xc;
private const string Window_ClassName = "WindowsForms10.Window.8.app.0.378734a";
private const string Window_Caption = "Form1";
private const string Edit_ClassName = "WindowsForms10.EDIT.app.0.378734a";


private const string Combo_ClassName = "WindowsForms10.COMBOBOX.app.0.378734a";



//get main window handle
IntPtr window_hwnd = FindWindow(Window_ClassName, Window_Caption);


if (!(window_hwnd == IntPtr.Zero)) {


//find first textbox or edit handle with classname on the main window
List<IntPtr> text_hwndlist = new List<IntPtr>();
IntPtr text_hwnd = FindWindowEx(window_hwnd, IntPtr.Zero, Edit_ClassName, null);


//reapte last level to find all edit handle
//when findwindowex return 0 then it cant find nothing more so we have all edit on main window
while (!(text_hwnd == IntPtr.Zero)) {
text_hwndlist.Add(text_hwnd);
text_hwnd = FindWindowEx(window_hwnd, text_hwnd, Edit_ClassName, null);
}


//loop edits handle and send set-text message to them
for (Int32 i = 0; i <= text_hwndlist.Count - 1; i++) {
SendMessage(text_hwndlist[i], WM_SETTEXT, IntPtr.Zero, "Edit index is : " + i.ToString());
}


//do same thing with combobox
IntPtr combo_hwnd = FindWindowEx(window_hwnd, IntPtr.Zero, Combo_ClassName, null);
SendMessage(combo_hwnd, WM_SETTEXT, IntPtr.Zero, "Combo");
}