दूसरे दिन, एक लंबे ब्रेक के बाद, मुझे WPF पर काम करना पड़ा, और विंडोज 7 के कष्टप्रद मानक दृश्य को कुछ और प्रेरणादायक के साथ बदलने की इच्छा थी, विजुअल स्टूडियो 2012 की शैली में कहें:
मैं इसके लिए विंडोज 8 पर स्विच नहीं करना चाहता था, साथ ही परियोजनाओं के लिए मेट्रो जैसी पुस्तकालयों के लिंक जोड़ना और उन्हें छांटना - यह अगला कदम होगा। इस बीच, शाम को खर्च करना और काम करने वाले कोड में न्यूनतम परिवर्तन के साथ इस तरह के परिणाम को प्राप्त करना दिलचस्प था। आगे देखते हुए, मैं कहूंगा कि परिणाम, जैसा कि योजनाबद्ध था, बहुत साफ निकला: निम्नलिखित कोड का एक टुकड़ा, स्पष्टता के लिए गायब कुछ विशेषताओं को छोड़कर, यह पहले स्क्रीनशॉट से खिड़की है। सभी परिवर्तन शैली के कार्य तक सीमित थे।
3 दिसंबर को अपडेट करें: .net 4.5 (WindowChrome.Demo प्रोजेक्ट) में नई कक्षाओं का उपयोग करके एक वैकल्पिक कार्यान्वयन, रिपॉजिटरी में जोड़ा गया था, जो WinAPI के साथ देशी प्रोग्रामिंग के एक महत्वपूर्ण हिस्से से बचता था।
<Window ... Style="{StaticResource VS2012WindowStyle}"> <DockPanel> <StatusBar> <TextBlock>Ready</TextBlock> <StatusBarItem HorizontalAlignment="Right"> <ResizeGrip /> </StatusBarItem> </StatusBar> <TextBox Text="Hello, world!" /> </DockPanel> </Window>
अगला, मैं खिड़की की शैली बनाने में मुख्य बिंदुओं और नुकसान पर ध्यान केंद्रित करूंगा। यदि आप स्वयं स्रोतों से निपटना चाहते हैं या विवरण में जाए बिना इस शैली का उपयोग करना चाहते हैं, तो एक डेमो प्रोजेक्ट
गिथब पर उपलब्ध है।
मुख्य समस्या
WPF NC-area के साथ काम नहीं करता है। नेकां, यह "गैर-ग्राहक क्षेत्र" है, यह "गैर-ग्राहक भाग" है, यह क्रोम है, इसे निचले स्तर पर संसाधित किया जाता है। यदि आप विंडो तत्वों में से एक को बदलना चाहते हैं - एक सीमा, आइकन, शीर्षक या बटन, तो खोज करते समय पहली
टिप जो खिड़की की शैली को हटाने और सब कुछ खुद को रीमेक करने के लिए है। पूरी तरह से।
<Window AllowsTransparency="true" WindowStyle="None"> ...
WPF के विकास के पूरे इतिहास में, इस संबंध में बहुत कम बदलाव आया है। सौभाग्य से, मेरे पास ऑफिस 2007 के लिए स्टाइल पर एलेक्स यखिन की पुरानी पोस्ट का स्रोत कोड था, जिसे उन्होंने माइक्रोसॉफ्ट के लिए WPF को लोकप्रिय बनाने के लिए एक डेमो प्रोजेक्ट पर काम करते हुए लिखा था, इसलिए मुझे खरोंच से शुरू करने की धमकी नहीं थी।
नतीजतन, हमें एक शैली प्राप्त करने की आवश्यकता है, और यदि संभव हो तो, अतिरिक्त नियंत्रण के बिना: एक्सएएमएल प्रोजेक्ट ट्री और स्टाइल कोड में कस्टमाइंडविंडो डायरेक्टरी में स्थित हैं, और मुख्य विंडो प्रोजेक्ट रूट में है।
मैं परियोजना में नए पुस्तकालयों को जोड़ने से बचना चाहता था, लेकिन शैली को आसानी से किसी अन्य अनुप्रयोग में स्थानांतरित करने की क्षमता रखने के लिए, जिसने इस तरह की संरचना का निर्धारण किया।
एक शैली बनाएं
WPF में किसी अन्य नियंत्रण के लिए विंडो के लिए शैली, कंट्रोलटेम्पलेट का उपयोग करके सेट की गई है। विंडो की सामग्री ContentPresenter द्वारा प्रदर्शित की जाएगी, और सी # कोड में करना आसान है जो कार्यक्षमता संसाधन संसाधन में x: क्लास विशेषता के माध्यम से जुड़ा होगा। एक्सएएमएल के लिए सब कुछ बहुत मानक है।
<ResourceDictionary x:Class="Whush.Demo.Styles.CustomizedWindow.VS2012WindowStyle"> <Style x:Key="VS2012WindowStyle" TargetType="{x:Type Window}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Window}"> <ContentPresenter /> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
स्टूडियो 2012 की शैली में विंडो कंट्रोल बटन को तुरंत परिभाषित करें। यदि आप बाद में एप्लिकेशन में ऐसे बटन का उपयोग करना चाहते हैं तो यह एकमात्र अतिरिक्त वैश्विक शैली होगी।
हमें एक नियमित बटन की कार्यक्षमता की आवश्यकता है, लेकिन एक बहुत ही आदिम प्रतिपादन के साथ - वास्तव में, केवल पृष्ठभूमि और सामग्री।
Xaml शैली बटन <Style x:Key="VS2012WindowStyleTitleBarButton" TargetType="{x:Type Button}"> <Setter Property="Focusable" Value="false" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Button}"> <Grid> <Border x:Name="border" Background="Transparent" /> <ContentPresenter /> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="border" Property="Background" Value="#FFF" /> <Setter TargetName="border" Property="Opacity" Value="0.7" /> </Trigger> <Trigger Property="IsPressed" Value="True"> <Setter TargetName="border" Property="Background" Value="{StaticResource VS2012WindowBorderBrush}"/> <Setter TargetName="border" Property="Opacity" Value="1" /> <Setter Property="Foreground" Value="#FFF"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
बटनों पर चित्र "वेक्टर में" बनाना सबसे आसान है। उदाहरण के लिए, अधिकतम इस तरह दिखता है:
<Path StrokeThickness="1" RenderOptions.EdgeMode="Aliased" Data="M0,0 H8 V8 H0 V0 M0,1 H8 M0,2 H8" />
शीर्षक पाठ के लिए, मानक Segoe UI फ़ॉन्ट का उपयोग करें। यहां एकमात्र विशेषता यह सुनिश्चित करना है कि पाठ को धुंधला किए बिना खींचा गया है, अन्यथा खिड़की का शीर्षक दिखेगा ... यह बुरा लगेगा - जैसे स्क्रीनशॉट में दूसरी पंक्ति।
वैसे, एक ही उद्देश्य के साथ बटनों पर पथ के लिए, एजमोड = "अलियासेड" का उपयोग किया गया था, और
WPF 4+ में पाठ के लिए, एक लंबे समय से प्रतीक्षित अवसर यह दर्शाता है कि यह डिस्प्ले पर प्रदर्शित होगा, न कि "आदर्श डिवाइस" पर, जिसने हमें हमारे गैर-आदर्श स्क्रीन पर स्वीकार्य स्पष्टता प्राप्त करने की अनुमति दी।
<TextBlock TextOptions.TextRenderingMode="ClearType" TextOptions.TextFormattingMode="Display" > ...
एक और दिलचस्प विशेषता "विंडोज 7 की ज्यामिति" से जुड़ी है जब एक विंडो को पूर्ण स्क्रीन पर खोला जाता है। विंडो को स्केल करके विंडोज धोखा देती है ताकि बॉर्डर पूरी तरह से स्क्रीन के बॉर्डर से परे चला जाए, जिससे मॉनिटर पर विंडो का केवल क्लाइंट हिस्सा ही रह जाए। स्वाभाविक रूप से, विंडोज अब एक सीमा नहीं खींचता है, और मानक खिड़कियों के लिए सब कुछ उम्मीद के मुताबिक काम करता है। WPF इस तरह से काम नहीं करता है और हमारी तरह की खिड़कियों के लिए, छवि का कुछ हिस्सा खोने या पड़ोसी के मॉनिटर से जुड़ने पर शुरू होने का जोखिम होता है।
शेष विवरण कम महत्वपूर्ण हैं, लेकिन यदि आप रुचि रखते हैं, तो
स्रोत में आपका स्वागत है।
विंडो को रिवाइज करें
.नेट 4.0
बटन और आइकन पर प्रतिक्रिया के अलावा, विंडो को स्थानांतरित करना चाहिए और जब किनारों और कोनों के लिए शीर्षक के लिए ड्रैग करें, तो आकार बदल सकते हैं। संबंधित हॉट ज़ोन अदृश्य नियंत्रणों का उपयोग करके आसानी से सेट किए जाते हैं। ऊपरी बाएं (उत्तर-पश्चिम) कोने के लिए एक उदाहरण।
<Rectangle x:Name="rectSizeNorthWest" MouseDown="OnSizeNorthWest" Cursor="SizeNWSE" Fill="Transparent" VerticalAlignment="Top" HorizontalAlignment="Left" Width="5" Height="5" />
यदि क्लास विशेषता संसाधनों में मौजूद है, तो इस क्लास के तरीकों को साधारण ईवेंट हैंडलर के रूप में नाम से बुलाया जा सकता है, जिसका हमने उपयोग किया था। हैंडलबार खुद, जैसे कि मिनबुट्टनक्लिक और ऑनसाइज़ नॉर्थवेस्ट, कुछ इस तरह दिखते हैं:
void MinButtonClick(object sender, RoutedEventArgs e) { Window window = ((FrameworkElement)sender).TemplatedParent as Window; if (window != null) window.WindowState = WindowState.Minimized; } void OnSizeNorthWest(object sender) { if (Mouse.LeftButton == MouseButtonState.Pressed) { Window window = ((FrameworkElement)sender).TemplatedParent as Window; if (window != null && window.WindowState == WindowState.Normal) { DragSize(w.GetWindowHandle(), SizingAction.NorthWest); } } }
ड्रैगसाइज़ तब WinAPI (
स्रोत ) को कॉल करती है और विंडोज को पूर्व-डोनेट समय के अनुसार विंडो के आकार बदलने के लिए मजबूर करती है।
.नेट 4.5
4.5 में, सुविधाजनक कक्षाएं
SystemCommands और
WindowChrome दिखाई दीं । जब एक विंडो में जोड़ा जाता है, तो विंडोक्रोम खिड़की के आकार, स्थिति और स्थिति को बदलने का कार्य करता है, और हमें "वैश्विक" समस्याओं के साथ छोड़ देता है।
<Setter Property="WindowChrome.WindowChrome"> <Setter.Value> <WindowChrome NonClientFrameEdges="None" GlassFrameThickness="0" ResizeBorderThickness="7" CaptionHeight="32" CornerRadius="0" /> </Setter.Value> </Setter>
यदि वांछित है, तो आप .net 4.0 पर WindowChrome का उपयोग कर सकते हैं, लेकिन आपको अतिरिक्त पुस्तकालयों को जोड़ना होगा, जैसे
WPFShell (मदद के लिए धन्यवाद
afsherman )।
लगभग किया हुआ। जब विंडो की स्थिति बदलती है, तो हम इंटरफ़ेस परिवर्तनों को नियंत्रित करने के लिए ट्रिगर करते हैं। चलो XAML पर वापस जाते हैं और उदाहरण के लिए, Window.IsActive के मान के आधार पर StatusBars रंग बदलते हैं।
StatusBar के लिए XAML <Style.Resources> <Style TargetType="{x:Type StatusBar}"> <Style.Triggers> <DataTrigger Value="True" Binding="{Binding IsActive, RelativeSource={RelativeSource AncestorType=Window}}"> <Setter Property="Foreground" Value="{StaticResource VS2012WindowStatusForeground}" /> <Setter Property="Background" Value="{StaticResource VS2012WindowBorderBrush}" /> </DataTrigger> <DataTrigger Value="False" Binding="{Binding IsActive, RelativeSource={RelativeSource AncestorType=Window}}" > <Setter Property="Foreground" Value="{StaticResource VS2012WindowStatusForegroundInactive}" /> <Setter Property="Background" Value="{StaticResource VS2012WindowBorderBrushInactive}" /> </DataTrigger> </Style.Triggers> </Style> </Style.Resources>
कृपया ध्यान दें कि यह शैली विंडो टेम्पलेट को प्रभावित नहीं करती है, लेकिन हमारी विंडो में रखे गए नियंत्रण हैं। कस्टम कोड के साथ बहुत पहले स्निपेट याद रखें?
<Window ... Style="{StaticResource VS2012WindowStyle}"> ... <StatusBarItem HorizontalAlignment="Right"> ... </Window>
यह इस StatusBar की शैली है जिसे हमने अब सेट किया है। यदि आप चाहते हैं और समय, आप नियंत्रण के अन्य वर्गों के लिए एक शैली भी सेट कर सकते हैं, उदाहरण के लिए, स्क्रॉलबार को ट्विक करें ताकि यह वांछित शैली से मेल खाता हो। लेकिन यह पहले से ही अगली शाम को एक व्यायाम होगा।
यह सब एक साथ रखना
वह सब है। हमें केवल एप्लिकेशन संसाधनों के माध्यम से परियोजना से शैली को जोड़ना होगा:
<Application ... StartupUri="MainWindow.xaml"> <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Styles/CustomizedWindow/VS2012WindowStyle.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> </Application>
और आप इसे किसी भी विंडो में उपयोग कर सकते हैं।
- डी।
पुनश्च एक बार फिर, गीथूब पर उन लोगों के लिए एक
लिंक जिन्होंने तुरंत उसकी खातिर नीचे स्क्रॉल किया।