ورود

View Full Version : بدست اوردن کنترل فعال در یک application



bmanfy
دوشنبه 11 مرداد 1389, 14:31 عصر
سلامک دوستان من تو فرم اصلی فرم برنامه ام یک شی application event قرار دادم که با استفاده از اون کلید های سراسری برنامه رو تعریف کردم .
مثلا اگر کلید F1 در کل برنامه فشرده بشه راهنما ی برنامه باز بشه .
و حالا میخوام وقتی کلید خاصی رو فشرد کنترلی که در کل برنامه مکان نما رو در اختیار داره رو دریافت کنه مثلا فرض کنید تو کل برنامه اگر کلید Cltrl+T فشرده شده بشه و کنترلی که هم اکنون مکان نما رو در اختیا رداشته باشه از نوع TEdit باشه مقدارش رو برابر با زمان فعلی سیستم قرار بده .
عملابا بخش اول(بدست اوردن کلید فشرده شده) و اخر(انتساب زمان) مشکلی ندارم و تنها مشکل در بخش دوم یعنی بدست اوردن کنترل فعال بر برنامه است .
ممنون از همگی.

مهران رسا
دوشنبه 11 مرداد 1389, 17:02 عصر
مثلا فرض کنید تو کل برنامه اگر کلید Cltrl+T فشرده شده بشه و کنترلی که هم اکنون مکان نما رو در اختیا رداشته باشه از نوع TEdit باشه مقدارش رو برابر با زمان فعلی سیستم قرار بده .
خب در رویداد Edit کدتون رو بنویسید !

Felony
دوشنبه 11 مرداد 1389, 17:38 عصر
به وسیله تابع GetFocus میتونید هندل کنترل جاری رو بگیرید ، براتون یه نمونه نوشتم ، کد زیر رو در رویداد OnKeyPress فرم برنامتون بنویسید :

var
i: Integer;
CurControl_HWND: THandle;
CurControl_Str: String;
begin
// Get current control handle
CurControl_HWND:= GetFocus;

// Check all control on form & find control that Handle of it = CurControl
for i:= 0 to Self.ComponentCount - 1 do
begin
if Components[i] is TWinControl then
if CurControl_HWND<> TWinControl(Components[i]).Handle then
Continue
else
begin
CurControl_Str:= TWinControl(Components[i]).ClassName;
if CurControl_Str= 'TEdit' then
TEdit(Components[i]).Text:= DateToStr(Now);
if CurControl_Str= 'TMemo' then
TMemo(Components[i]).Lines.Add(DateToStr(Now));
if CurControl_Str= 'TButton' then
ShowMessage('This is a TButton control');
end;
end;

tdkhakpur
دوشنبه 11 مرداد 1389, 18:06 عصر
var
str : string;
begin
str := 'demo';
SendMessage(GetFocus(), WM_SETTEXT, 0, WPARAM(str));
end;

Felony
دوشنبه 11 مرداد 1389, 21:22 عصر
var
str : string;
begin
str := 'demo';
SendMessage(GetFocus(), WM_SETTEXT, 0, WPARAM(str));
end;



رو در اختیا رداشته باشه از نوع TEdit باشه مقدارش رو برابر با زمان فعلی سیستم قرار بده .

کد شما درست عمل میکنه ولی نمیشه روش کنترلی داشت ، یعنی نمیشه تعیین کرد اگر کنترل جاری از کلاس TEdit بود بعد متن رو درج کنه ، در این صورت تو برنامه رو هر کنترلی که فوکوس شده باشه متنش عوض میشه .

tdkhakpur
دوشنبه 11 مرداد 1389, 22:59 عصر
یعنی نمیشه تعیین کرد اگر کنترل جاری از کلاس TEdit بود بعد متن رو درج کنه ، در این صورت تو برنامه رو هر کنترلی که فوکوس شده باشه متنش عوض میشه
کار چندان سختی نیست


var
ptr : array [0..256] of char;
str : string;
begin
str := 'Demo';
GetClassName( GetFocus(), ptr, 256);
if AnsiString(ptr)= 'TEdit' then
SendMessage(GetFocus(), WM_SETTEXT, 0, WPARAM(str));
end;

bmanfy
دوشنبه 11 مرداد 1389, 23:16 عصر
ممنون از پاسخ همگی


خب در رویداد Edit کدتون رو بنویسید

این نمیشه و یه کمی غیر منطقی میشه چون برنامه ای هست که نوشتم و حدودا 100 تا فرم داره و تو هر فرم هم کلی جعبه متن و خیلی سخت و طولانی میشه و ....

و راه حل بعدی :


به وسیله تابع GetFocus میتونید هندل کنترل جاری رو بگیرید ، براتون یه نمونه نوشتم ، کد زیر رو در رویداد OnKeyPress فرم برنامتون بنویسید :

ممنون از نمونه کدی که نوشتید . کدی نوشتید برای تک تک فرم ها نوشته در حالی که من قصد دارم رو فرم اصلی برنامه بنویسم و بتونم کنترل فعال رو در هر فرمی که فعال باشه به دست بیارم .
و در ضمن فکر میکنم یک مقداری کدی که نوشتید رو میشه راحتر تر هم نوشت برای هر فرم به صورت زیر :



if ActiveControl.ClassType = TEdit then
TEdit(ActiveControl).Text := 'edit'
else if ActiveControl.ClassType = TMemo then
TMemo(ActiveControl).Lines.Text := 'mamo'

bmanfy
دوشنبه 11 مرداد 1389, 23:22 عصر
در باره راه حل tdkhalpur هم که مشکلی که داشت اشاره شد و برای رفع مشکلش هم کدی دوباه ارائه دادند . و البته درست هم است .
اما هنوز کار من رو راه نمیندازه .
اجازه بدین یه کم صورت مسئله رو باز تر کنم :
حالا بعد از این که نوع کلاس شی فعال مشخص شد میخوام بتونم شی فعال رو به متغیری از همون نوع کلاس ارسال کنم تا بتونم کلیه خصوصیات اون رو بررسی کنم و با توجه به این خصوصیات مقدار جدید که لازم دارم رو به اون انتساب بدم :

فرض کنید میخوام کنترل های نوع TMaskEdit رو دریافت و چک کنم که EditMask اون چیه و توجه به خصوصیت مقدار Text اون رو مشخص کنم .

bmanfy
دوشنبه 11 مرداد 1389, 23:25 عصر
ببخشید یک سوالی که یادم رفت بپرسم درباره THandel این چه نوعیه و یا HWND دقیقا اینا چیه؟ و به چه شکل میشه از اینها استفاده کرد؟ و کجا کاربرد داره ؟

ممنون ار همگی

tdkhakpur
سه شنبه 12 مرداد 1389, 00:34 صبح
فرض کنید میخوام کنترل های نوع TMaskEdit رو دریافت و چک کنم که EditMask اون چیه و توجه به خصوصیت مقدار Text اون رو مشخص کنم

برای این کار شما باید از تنظیمات خود اشیا استفاده کنید یعنی با استفاده از خصوصیات شی پیدا شده شی جدید از همان نوع ایجاد کنید به این شکل :


var
tmpEdit : TEdit;
begin
tmpEdit := TEdit(ActiveControl).
tmpEdit.Top := tmpEdit.Top+100;
end;

البته این کار صحیح نیست فقط برای زمانی که ساختار هر دو شی یکسان باشد میتواند جواب دقیق دهد چون ممکن هست یک شخص شیئی با همان نام را رجیستر کرده باشد که با شی شما متفاوت باشد..


درباره THandel این چه نوعیه و یا HWND دقیقا اینا چیه؟ و
هر دو یک مقدار عددی هستند که برای دسترسی به کنترلها استفاده میشود.


به چه شکل میشه از اینها استفاده کرد؟ و کجا کاربرد داره

خب بیشتر برای ارسال پیغام یا پیدا کردن نام یک کنترل و بسیاری جاهای دیگر .

bmanfy
سه شنبه 12 مرداد 1389, 01:15 صبح
برای این کار شما باید از تنظیمات خود اشیا استفاده کنید یعنی با استفاده از خصوصیات شی پیدا شده شی جدید از همان نوع ایجاد کنید به این شکل :


نه نه . نباید ساخته بشه که .
اصلا خصوصیات شی پیدا شده رو بدسا اورد ؟

بزارین دقیق بگم میخوام چیکار کنم:
ببینید برنامه نوشتم که کلی فرم داره و تو این فرم ها ای TMaskEdit اسفاده کردم برای ساعت و تاریخ
حالا تو فرم اصلا برنامه یک aplictionEvent قرار دادم و می خوام مشخص بکنم در هر فرمی از برنامه اگر کلید مثلا f12 فشرده شد اگر شی از نوع TMaskEdit باشه و خصوصیت EditMask اون برابر باشه با 00/00/00 تو اون بیاد تاریخ روز رو وارد کنه و اگر خصوصیت EditMask اون00:00 باشه زمان فعلی رو وارد کنه .

کدهایی که گفتید درسته و خوب کار میکنه فقط میمونه چه ظوری EditMAsk شی رو چک کنم ؟

tdkhakpur
سه شنبه 12 مرداد 1389, 01:32 صبح
به فرض شما توانستید به کنترل دسترسی پیدا کنید و MaskEdit1 همانی هست که شما در نظر دارید خب با یک الگوریتم ساده بررسی کنید!!


var
DateTime :SYSTEMTIME;
begin
GetLocalTime(DateTime);
if MaskEdit1.Text = '00/00/00' then
MaskEdit1.Text := IntTostr(DateTime.wYear)+ '/' +
IntTostr(DateTime.wMonth)+ '/' +
IntTostr(DateTime.wDay)
else
if MaskEdit1.Text = '00:00:00' then
MaskEdit1.Text := IntTostr(DateTime.wHour)+ ':' +
IntTostr(DateTime.wMinute)+ ':' +
IntTostr(DateTime.wSecond);
end;

Felony
سه شنبه 12 مرداد 1389, 13:06 عصر
اگر میخواین در تمام فرم های برنامه این کار رو انجام بدید یا باید کلیدهای صفحه کلید رو در سطح برنامه هوک کنید یا در تمام فرمهاتون این کد رو بنویسید ، یا یک تابع بنویسید و نام فرم جاری رو به عنوان پارامتر بهش بدید و تو همه فرم های برنامه تابع رو صدا بزنید و نام فرم جاری رو بهش پاس بدید و داخل تابع با فرم جاری کارهای مورد نظرتون رو انجام بدید .

SAASTN
سه شنبه 12 مرداد 1389, 23:12 عصر
ربطی به سوال تاپیک نداره ولی به نظر من راه اصولی برای انجام چیزی که شما فرمودید اینه که TMaskEdit بازنویسی بشه:
type
TMyMaskEdit = class(TMaskEdit)
protected
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
end;

{ TMyMaskEdit }

procedure TMyMaskEdit.KeyDown(var Key: Word; Shift: TShiftState);
begin
inherited;
if Key = VK_F12 then
if EditMask = '00/00/00' then
Text := '99/99/99';
end;

bmanfy
چهارشنبه 13 مرداد 1389, 00:32 صبح
فرض شما توانستید به کنترل دسترسی پیدا کنید و MaskEdit1 همانی هست که شما در نظر دارید خب با یک الگوریتم ساده بررسی کنید!!


با تشکر از پاسختون . این الگوریتم ساده رو بردم . مشکل من سر همون فرض ابتدایی است .
یعنی همین که بتونم کنترل رو بدست بیارم .
یعنی تو یه application چه طور میشه یک کنترل فعال رو تمام و کمال بدست اورد ؟

bmanfy
چهارشنبه 13 مرداد 1389, 00:34 صبح
اگر میخواین در تمام فرم های برنامه این کار رو انجام بدید یا باید کلیدهای صفحه کلید رو در سطح برنامه هوک کنید یا در تمام فرمهاتون این کد رو بنویسید ، یا یک تابع بنویسید و نام فرم جاری رو به عنوان پارامتر بهش بدید و تو همه فرم های برنامه تابع رو صدا بزنید و نام فرم جاری رو بهش پاس بدید و داخل تابع با فرم جاری کارهای مورد نظرتون رو انجام بدید .


خب البته اگر بخوام که تو همه فرم ها بنویسم که ساد است . نه نمیخوام تو تمام فرم ها بنویسم .
فقط تو فرم اصلی برنامه .

کلید رو هوک کردن یعنی چی ؟

bmanfy
چهارشنبه 13 مرداد 1389, 00:40 صبح
ربطی به سوال تاپیک نداره ولی به نظر من راه اصولی برای انجام چیزی که شما فرمودید اینه که TMaskEdit بازنویسی بشه:


خب اره . راه جل جالبیه . اما خب پروژه نوته شده و نمیشه تمام شی ها رو تعویض کزر دیگه .


البته فکر میکنم روشی که دارم خودم میگم خیلی راحت و بی دردسره . فقط مونده یه کاری رو انجام بدم .

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

Felony
چهارشنبه 13 مرداد 1389, 05:48 صبح
خب اره . راه جل جالبیه . اما خب پروژه نوته شده و نمیشه تمام شی ها رو تعویض کزر دیگه .


البته فکر میکنم روشی که دارم خودم میگم خیلی راحت و بی دردسره . فقط مونده یه کاری رو انجام بدم .

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

با استفاده از همون کد قبلی که براتون نوشتم میتونید این کار رو انجام بدید ، فقط باید کمی تغییر درش ایجا بشه ، کد جدیدی که براتون نوشتم این کار رو انجام میده :
var
FormCount, ControlCount: Integer;
CurControl_HWND: THandle;
CurControl_Str: String;
CurControl_TC: TComponent;
begin
// Get current control handle
CurControl_HWND:= GetFocus;

// Check all control on form & find control that Handle of it = CurControl
for FormCount:= 0 to Application.ComponentCount - 1 do
if Application.Components[FormCount] is TForm then
for ControlCount:= 0 to TForm(Application.Components[FormCount]).ComponentCount - 1 do
begin
CurControl_TC:= TForm(Application.Components[FormCount]).Components[ControlCount];
if CurControl_TC is TWinControl then
if CurControl_HWND<> TWinControl(CurControl_TC).Handle then
Continue
else
begin
CurControl_Str:= TWinControl(CurControl_TC).ClassName;
if CurControl_Str= 'TEdit' then
TEdit(CurControl_TC).Text:= DateToStr(Now);
if CurControl_Str= 'TMemo' then
TMemo(CurControl_TC).Lines.Add(DateToStr(Now));
if CurControl_Str= 'TMaskEdit' then
if TMaskEdit(CurControl_TC).EditMask = '!90:00;1;_' then
TMaskEdit(CurControl_TC).Text:= '06:15';
end;
end;
end;

bmanfy
چهارشنبه 13 مرداد 1389, 11:22 صبح
ممنون از كدي كه نوشتين .

تو اين كد شما تمام فرم ها و كنترل ها رو پيمايش كردين .
يعني كد مستقيمي وجود نداره كه بتونه كنترل فعال رو بده ؟مثل همين GetFocus.
يا از روي همين Handle كه با تابع GetFocus بدست مياد مستقيم رفت سر كنترل فعال؟

Felony
چهارشنبه 13 مرداد 1389, 13:14 عصر
ممنون از كدي كه نوشتين .

تو اين كد شما تمام فرم ها و كنترل ها رو پيمايش كردين .
يعني كد مستقيمي وجود نداره كه بتونه كنترل فعال رو بده ؟مثل همين GetFocus.
يا از روي همين Handle كه با تابع GetFocus بدست مياد مستقيم رفت سر كنترل فعال؟

کد مستقیم چه نوع داده ای به شما برگشت بده ؟!
الان شما مثلا تو فرم 7 برنامتون و روی کنترل Edit شماره 20 هستید ، تایع باید چی به عنوان کنترل جاری به شما بده ؟ مثلا تابعی مثل ActiveControl باشه و وقتی صداش زدید مقدار بازگشتیش این باشه : Form7.Edit20 ؟!

در کل همچین فکری غیر منطقی هست ، این کد هم سرعتش خوب هست و هیچ مشکلی در پاسخگویی به نیاز شما نداره .

کد قبلی یک خط اضافی داشت که حذفش کردم :

var
FormCount, ControlCount: Integer;
CurControl_HWND: THandle;
CurControl_Str: String;
CurControl_TC: TComponent;
begin
// Get current control handle
CurControl_HWND:= GetFocus;

// Check all control on form & find control that Handle of it = CurControl
for FormCount:= 0 to Application.ComponentCount - 1 do
if Application.Components[FormCount] is TForm then
for ControlCount:= 0 to TForm(Application.Components[FormCount]).ComponentCount - 1 do
begin
CurControl_TC:= TForm(Application.Components[FormCount]).Components[ControlCount];
if CurControl_TC is TWinControl then
if CurControl_HWND= TWinControl(CurControl_TC).Handle then
begin
CurControl_Str:= TWinControl(CurControl_TC).ClassName;
if CurControl_Str= 'TEdit' then
TEdit(CurControl_TC).Text:= DateToStr(Now);
if CurControl_Str= 'TMemo' then
TMemo(CurControl_TC).Lines.Add(DateToStr(Now));
if CurControl_Str= 'TMaskEdit' then
if TMaskEdit(CurControl_TC).EditMask = '!90:00;1;_' then
TMaskEdit(CurControl_TC).Text:= '06:15';
end;
end;
end;

bmanfy
چهارشنبه 13 مرداد 1389, 14:01 عصر
ممنون از لطفتون.
اره اين كد رو كه ميدونم جواب ميده و درسته .


الان شما مثلا تو فرم 7 برنامتون و روی کنترل Edit شماره 20 هستید ، تایع باید چی به عنوان کنترل جاری به شما بده ؟ مثلا تابعی مثل ActiveControl باشه و وقتی صداش زدید مقدار بازگشتیش این باشه : Form7.Edit20 ؟!

در کل همچین فکری غیر منطقی هست ، این کد هم سرعتش خوب هست و هیچ مشکلی در پاسخگویی به نیاز شما نداره .

.

البته اره اين هم هست .
دستور مستقيم براي بدست اوردن فرمي كه اكتيو هست چي؟

bmanfy
چهارشنبه 13 مرداد 1389, 14:08 عصر
راستش من هميشه سعي ميكنم كوتاهترين كد رو بنويسم.
البته اگر بخواهيم با كد شما كار كنيم . ديگه لازم نيست فرم رو هم پيكايش كنيم .
با ActiveControl كنترل فعال رو ميگيريم .



curControl_HWND := GetFocus;
for i:= 0 to Application.ComponentCount-1 do
begin
if Application.Components[i] is TForm then
begin
curForm := TForm(Application.Components[i]);
if curForm.Active then
begin
curControl := curForm.ActiveControl;
if curControl.ClassType = TAdvMaskEdit then
begin
if TAdvMaskEdit(curControl).EditMask ='99/99/99;1;0' then
TAdvMaskEdit(curControl).Text := _Date
else if TAdvMaskEdit(curControl).EditMask ='99/99;1;0' then
TAdvMaskEdit(curControl).Text := _Time;
end;
end;


حالا يك كد ميانبر براي فرم فعال ؟!!!!!

bmanfy
چهارشنبه 13 مرداد 1389, 14:35 عصر
ممنون از همگي دوستان
جواب نهايي رو بدست اوردم كه به شكل زير است :
براي بدست اوردن كنترل فعال در سطح application ميتونيم از دستور زير استفاده كنيم :


screen.ActiveControl;

كه خروجي اون از نوع TWincontrol است .
و براي بدست اوردن فرم فعال نيز از دستور زير :


Screen.ActiveForm;

كه خروجي اين دستور از نوع TForm است .

و كد نهايي كه نوشتم هم به صورت زير است .


curControl := Screen.ActiveControl;
if (curControl.ClassType = TAdvMaskEdit) then
begin
if TAdvMaskEdit(curControl).EditMask='99/99/99;1;0' then
TAdvMaskEdit(curControl).Text := _Date
else if (TAdvMaskEdit(curControl).EditMask='99:99;1;0') then
TAdvMaskEdit(curControl).Text := _Time;
end;