2011-12-29 5 views
6

मैं एक बटन बनाने की कोशिश कर रहा हूं जो माउस पर इंगित करता है जब चमकता है। इन रंगों में एक चिकनी लुप्तप्राय को नियंत्रित करने के लिए पृष्ठभूमि में एक टाइमर होना चाहिए। यह एक रंग से अगले रंग तक नहीं कूदता है, यह धीरे-धीरे अगले रंग में फहराता है।रीयल-टाइम चमकते प्रभाव देने के लिए रंगों का उपयोग कैसे करें?

अब मेरी समस्या यह है कि जब यह अपने नियमित रंग में वापस आ जाता है, तो यह अपने अंतिम रंग में बंद नहीं होता है। वास्तव में, यह प्रकाश से अंधेरे में कूदता रहता है।

यह मेरा एक कस्टम बटन है, जिसे मैं कोड पोस्ट नहीं कर रहा हूं, लेकिन यह कोड माउस एंटर/एक्ज़िट इवेंट और रंगीन संपत्ति के साथ कुछ भी रखा जा सकता है।

यह एक चर FMenuDestColor सेट करके काम करता है। ExtractColor रंग के आधार पर आरजीबी मान प्राप्त करता है। टाइमर वर्तमान रंग और गंतव्य रंग के बीच प्रत्येक आरजीबी चैनल की तुलना करता है। फिर टाइमर अगले रंग को फीका करने के लिए वर्तमान रंग को संशोधित करता है। ये गणना CalcColorFade नामक फ़ंक्शन में की जाती है - प्रत्येक चैनल के लिए 3 बार चलाएं।

procedure ExtractColor(const Color: TColor; var R, G, B: Byte); 
begin 
    R:= GetRValue(Color); 
    G:= GetGValue(Color); 
    B:= GetBValue(Color); 
end; 

function CalcColorFade(const C1, C2: Byte): Byte; 
const 
    RGB_MULT = 1.2; 
    RGB_SENS = 5; 
begin 
    if C1 <> C2 then begin  
    if (C1 >= C2 - RGB_SENS) and (C1 <= C2 + RGB_SENS) then 
     Result:= C2 
    else 
     if C1 > C2 then 
     Result:= EnsureRange(Trunc(C1/RGB_MULT), 0, 255) 
     else 
     Result:= EnsureRange(Trunc(C1 * RGB_MULT), 0, 255); 
    end else begin 
    Result:= C2; 
    end; 
end; 

procedure TfrmMain.tmrMenuGlowTimer(Sender: TObject); 
var 
    R1, G1, B1: Byte; 
    R2, G2, B2: Byte; 
    R3, G3, B3: Byte; 
begin 
    if MenuButton.Color <> FMenuDestColor then begin 
    ExtractColor(MenuButton.Color, R1, G1, B1); 
    ExtractColor(FMenuDestColor, R2, G2, B2); 
    R3:= CalcColorFade(R1, R2); 
    G3:= CalcColorFade(G1, G2); 
    B3:= CalcColorFade(B1, B2); 
    MenuButton.Color:= RGB(R3, G3, B3); 
    end; 
end; 

procedure TfrmMain.MenuButtonMouseEnter(Sender: TObject); 
begin 
    FMenuDestColor:= clBlue; 
end; 

procedure TfrmMain.MenuButtonMouseLeave(Sender: TObject); 
begin 
    FMenuDestColor:= clNavy; 
end; 

माउस को उस पर इंगित करें, और यह अगले रंग में फीका होगा। लेकिन माउस को इसके बाहर ले जाएं, और यह थोड़े अपने मूल रंग में स्थिति में बंद नहीं होता है - यह प्रकाश और अंधेरे के बीच आगे और पीछे हिलाता है।

मुझे लगता है कि मैं जो कर रहा हूं उसे पूरा करने के लिए एक क्लीनर दृष्टिकोण होना चाहिए, और मैं उन सुझावों के लिए भी खुला हूं।

टाइमर का अंतराल 70 पर है और 1.2 की स्थिरता, 1.1 में बदलकर, यह ठीक काम करता है। तो 1.2 को बदलने के बारे में कुछ ऐसा है जो इसे गड़बड़ कर देता है।

+1

मुझे लगता है कि यदि आप समान कोड हैंडलिंग आर, जी, और बी और कारक को स्वयं की प्रक्रिया में रखते हैं और इसे तीन बार कहते हैं तो आपको अपना कोड पढ़ने में आसान लगेगा: 'आर 1' और 'आर 2 में गुजरना पहले रन पर, दूसरे रन पर 'जी 1' और' जी 2 'इत्यादि। – sarnold

+0

@ कर्नाल्ड अच्छी युक्ति जो मैं वैसे भी घायल हो जाती, हालांकि सवाल से असंबंधित। –

+0

पर्याप्त सच है, इसलिए मैंने इसे एक टिप्पणी के रूप में छोड़ा - मैं उस समस्या को नहीं देख सकता जिसे आप _actually_ हल करने की कोशिश कर रहे हैं। बस संकेत देते हुए कि यह उन ब्लॉकों में तीन गुना के बजाय केवल एक बार ठीक करना आसान होगा ... :) – sarnold

उत्तर

1

समस्या को अन्य स्थिर RGB_SENS से 7 समायोजित करके हल किया गया था।

तो ऐसा लगता है कि मैं RGB_MULT के साथ जितना अधिक जाता हूं, उतना ही मुझे RGB_SENS लेना होगा।

क्या होता है यह पहले नियंत्रण का वर्तमान रंग प्राप्त करता है, फिर गंतव्य रंग मिलता है, उन रंगों में से प्रत्येक रंग को आरजीबी चैनलों में विभाजित करता है, फिर उन चैनलों में से प्रत्येक के लिए यह "नया" आरजीबी प्राप्त करने के लिए करता है मूल्य ...

function DoCalc(const Curr, Dest: Byte): Byte; 
const 
    RGB_MULT = 1.2; //How much color change per step 
    RGB_SENS = 10; //Distance from dest +/- until "locked" into dest 
begin 
    if Curr <> Dest then begin 
    if (Curr >= Dest - RGB_SENS) and (Curr <= Dest + RGB_SENS) then begin 
     Result:= Dest; //Lock color into destination (sensitivity) 
    end else begin 
     if Curr > Dest then begin //Needs to go down 
     Result:= EnsureRange(Trunc(Curr/RGB_MULT), 0, 255); 
     end else begin   //Needs to go up 
     Result:= EnsureRange(Trunc(Curr * RGB_MULT), 0, 255); 
     end; 
    end; 
    end else begin 
    Result:= Dest; //Just return the dest color, no change 
    end; 
end; 

से पहले, RGB_MULT1.1 पर सेट किया जा करने के लिए इस्तेमाल किया, जो ठीक काम किया। लेकिन जब मैंने इसे 1.2 तक बढ़ा दिया, तब मेरी समस्या शुरू हुई। उस समय, RGB_SENS को 5 पर सेट किया गया था। RGB_SENS निर्धारित करता है कि गंतव्य रंग से कितना दूर तक रंग को "लॉक" जगह में रखना चाहिए। जाहिर है, 1.2 ने इस सीमा में कभी भी जमीन नहीं ली। RGB_SENS से 7 (और अब 10) का विस्तार करने के बाद, यह ठीक काम करता है।

+0

मजेदार बात यह है कि मैंने इस बात के लिए गणित लिखा है, फिर भी शब्दों में यह व्याख्या नहीं कर सकता कि यह वास्तव में कैसे काम कर रहा है: पीआई कोड भाषा में पढ़ना/बोलना है, मैं कोड को सादे अंग्रेजी में अनुवाद नहीं कर सकता ... –

+0

यह पूरी तरह से आम है। इसे भाषा में मजबूर करने की कोशिश न करें, कभी-कभी यह तर्क की सुंदरता के साथ गड़बड़ कर सकता है। : पी –

4

क्यों न केवल एचएसबी/एचएसवी मोड पर स्विच करें?

फिर आप अपना ह्यू (0-35 9) सेट कर सकते हैं, और संतृप्ति, चमक और अल्फा को नियंत्रित कर सकते हैं।

बाद वाले तीन में से प्रत्येक रोलिंग चमक प्रभाव के लिए विकल्प देता है।

+0

कूल, लेकिन क्या इसमें एक रंग से दूसरे रंग में मिश्रण शामिल है, उदाहरण के लिए, नीला से हरा? मेरा उद्देश्य एक रंग से दूसरे रंग में जाना है, न केवल थोड़ा हल्का या गहरा। –

+0

यदि आप रंग के माध्यम से रोल करते हैं, तो रंग बदल जाएंगे लेकिन सापेक्ष चमक और संतृप्ति बरकरार रहेंगी। – sarnold

+0

समझा, लेकिन यह किसी भी रंग से किसी अन्य रंग में जाने के लिए कैसे काम करेगा? लाल से हरा, नीला से बैंगनी, सियान से काला, सफेद से आकाश नीला, कोई निर्दिष्ट 2 रंग, मैं नहीं देखता कि यह कैसे काम करेगा। –

संबंधित मुद्दे