खोज…


परिचय

यहां लक्ष्य पारंपरिक मेनू और डायलॉग बॉक्स के साथ विंडोज प्रेजेंटेशन फाउंडेशन (WPF) का उपयोग करके F # में एक साधारण एप्लिकेशन का निर्माण करना है। यह F # और WPF के साथ काम करने वाले प्रलेखन, लेख और पोस्ट के सैकड़ों वर्गों के माध्यम से उतारा करने की कोशिश में मेरी हताशा से उपजा है। WPF के साथ कुछ भी करने के लिए, आपको इसके बारे में सब कुछ पता लगता है। यहाँ मेरा उद्देश्य एक आसान तरीका प्रदान करना है, एक सरल डेस्कटॉप प्रोजेक्ट जो आपके ऐप्स के लिए एक टेम्पलेट के रूप में काम कर सकता है।

प्रोजेक्ट सेट करें

हम मान लेंगे कि आप विजुअल स्टूडियो 2015 (VS 2015 कम्युनिटी, मेरे मामले में) कर रहे हैं। VS में एक खाली कंसोल प्रोजेक्ट बनाएँ। प्रोजेक्ट में | गुण आउटपुट प्रकार को Windows अनुप्रयोग में बदलते हैं।

अगला, प्रोजेक्ट में FsXaml.Wpf जोड़ने के लिए NuGet का उपयोग करें; यह पैकेज अनुमानित रीड कोपसे, जूनियर द्वारा बनाया गया था, और यह एफ # से WPF का उपयोग करके बहुत सरल करता है। स्थापना पर, यह कई अन्य WPF असेंबलियों को जोड़ेगा, इसलिए आपको नहीं करना होगा। FsXaml के समान अन्य पैकेज हैं, लेकिन मेरा एक लक्ष्य यह था कि समग्र परियोजना को यथासंभव सरल और मुख्य बनाने के लिए साधनों की संख्या को यथासंभव छोटा रखा जाए।

इसके अलावा, एक संदर्भ के रूप में UIAutomationTypes जोड़ें; यह .NET के भाग के रूप में आता है।

"व्यापार तर्क" जोड़ें

संभवतः, आपका कार्यक्रम कुछ करेगा। Program.fs के स्थान पर प्रोजेक्ट में अपना वर्किंग कोड जोड़ें। इस मामले में, हमारा काम एक विंडो कैनवस पर स्पाइरोग्राफ के घटता को आकर्षित करना है। यह नीचे Spirograph.fs का उपयोग करके पूरा किया गया है।

namespace Spirograph

// open System.Windows does not automatically open all its sub-modules, so we 
// have to open them explicitly as below, to get the resources noted for each.
open System                             // for Math.PI
open System.Windows                     // for Point
open System.Windows.Controls            // for Canvas
open System.Windows.Shapes              // for Ellipse
open System.Windows.Media               // for Brushes

// ------------------------------------------------------------------------------
// This file is first in the build sequence, so types should be defined here
type DialogBoxXaml  = FsXaml.XAML<"DialogBox.xaml">
type MainWindowXaml = FsXaml.XAML<"MainWindow.xaml">
type App            = FsXaml.XAML<"App.xaml"> 

// ------------------------------------------------------------------------------
// Model: This draws the Spirograph
type MColor = | MBlue   | MRed | MRandom

type Model() =
  let mutable myCanvas: Canvas = null
  let mutable myR              = 220    // outer circle radius
  let mutable myr              = 65     // inner circle radius
  let mutable myl              = 0.8    // pen position relative to inner circle
  let mutable myColor          = MBlue  // pen color
  
  let rng                      = new Random()
  let mutable myRandomColor    = Color.FromRgb(rng.Next(0, 255) |> byte,
                                               rng.Next(0, 255) |> byte,
                                               rng.Next(0, 255) |> byte)

  member this.MyCanvas
    with get() = myCanvas
    and  set(newCanvas) = myCanvas <- newCanvas

  member this.MyR
    with get() = myR
    and  set(newR) = myR <- newR

  member this.Myr
    with get() = myr
    and  set(newr) = myr <- newr

  member this.Myl
    with get() = myl
    and  set(newl) = myl <- newl

  member this.MyColor
    with get() = myColor
    and  set(newColor) = myColor <- newColor

  member this.Randomize =
    // Here we randomize the parameters. You can play with the possible ranges of
    // the parameters to find randomized spirographs that are pleasing to you.
    this.MyR      <- rng.Next(100, 500)
    this.Myr      <- rng.Next(this.MyR / 10, (9 * this.MyR) / 10)
    this.Myl      <- 0.1 + 0.8 * rng.NextDouble()
    this.MyColor  <- MRandom
    myRandomColor <- Color.FromRgb(rng.Next(0, 255) |> byte,
                                   rng.Next(0, 255) |> byte,
                                   rng.Next(0, 255) |> byte)

  member this.DrawSpirograph =
    // Draw a spirograph. Note there is some fussing with ints and floats; this 
    // is required because the outer and inner circle radii are integers. This is
    // necessary in order for the spirograph to return to its starting point 
    // after a certain number of revolutions of the outer circle.
    
    // Start with usual recursive gcd function and determine the gcd of the inner
    // and outer circle radii. Everything here should be in integers.
    let rec gcd x y =
        if y = 0 then x
        else gcd y (x % y)
  
    let g = gcd this.MyR this.Myr             // find greatest common divisor
    let maxRev = this.Myr / g                 // maximum revs to repeat

    // Determine width and height of window, location of center point, scaling 
    // factor so that spirograph fits within the window, ratio of inner and outer
    // radii.
    
    // Everything from this point down should be float.
    let width, height = myCanvas.ActualWidth, myCanvas.ActualHeight
    let cx, cy = width / 2.0, height / 2.0    // coordinates of center point
    let maxR   = min cx cy                    // maximum radius of outer circle
    let scale  = maxR / float(this.MyR)             // scaling factor
    let rRatio = float(this.Myr) / float(this.MyR)  // ratio of the radii

    // Build the collection of spirograph points, scaled to the window.
    let points = new PointCollection()
    for degrees in [0 .. 5 .. 360 * maxRev] do
      let angle = float(degrees) * Math.PI / 180.0
      let x, y = cx + scale * float(this.MyR) *
                 ((1.0-rRatio)*Math.Cos(angle) +
                  this.Myl*rRatio*Math.Cos((1.0-rRatio)*angle/rRatio)),
                 cy + scale * float(this.MyR) *
                 ((1.0-rRatio)*Math.Sin(angle) - 
                  this.Myl*rRatio*Math.Sin((1.0-rRatio)*angle/rRatio))
      points.Add(new Point(x, y))
  
    // Create the Polyline with the above PointCollection, erase the Canvas, and 
    // add the Polyline to the Canvas Children
    let brush = match this.MyColor with
                | MBlue   -> Brushes.Blue
                | MRed    -> Brushes.Red
                | MRandom -> new SolidColorBrush(myRandomColor)
  
    let mySpirograph = new Polyline()
    mySpirograph.Points <- points
    mySpirograph.Stroke <- brush

    myCanvas.Children.Clear()
    this.MyCanvas.Children.Add(mySpirograph) |> ignore

Spirograph.fs संकलन क्रम में पहली F # फ़ाइल है, इसलिए इसमें उन प्रकार की परिभाषाएँ शामिल हैं जिनकी हमें आवश्यकता होगी। इसका काम एक संवाद बॉक्स में दर्ज मापदंडों के आधार पर मुख्य विंडो कैनवस पर एक स्पिरोग्राफ को आकर्षित करना है। चूंकि स्पाइरोग्राफ बनाने के लिए बहुत सारे संदर्भ हैं, इसलिए हम यहां नहीं जाएंगे।

XAML में मुख्य विंडो बनाएँ

आपको एक XAML फ़ाइल बनानी होगी जो मुख्य विंडो को परिभाषित करती है जिसमें हमारा मेनू और ड्राइंग स्पेस शामिल है। यहाँ MainWindow.xaml में XAML कोड है:

<!-- This defines the main window, with a menu and a canvas. Note that the Height
     and Width are overridden in code to be 2/3 the dimensions of the screen -->
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Spirograph" Height="200" Width="300">
    <!-- Define a grid with 3 rows: Title bar, menu bar, and canvas. By default
         there is only one column -->
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <!-- Define the menu entries -->
        <Menu  Grid.Row="0">
            <MenuItem Header="File">
                <MenuItem Header="Exit"
                          Name="menuExit"/>
            </MenuItem>
            <MenuItem Header="Spirograph">
                <MenuItem Header="Parameters..."
                          Name="menuParameters"/>
                <MenuItem Header="Draw"
                          Name="menuDraw"/>
            </MenuItem>
            <MenuItem Header="Help">
                <MenuItem Header="About"
                          Name="menuAbout"/>
            </MenuItem>
        </Menu>
        <!-- This is a canvas for drawing on. If you don't specify the coordinates
             for Left and Top you will get NaN for those values -->
        <Canvas Grid.Row="1" Name="myCanvas" Left="0" Top="0">
        </Canvas>
    </Grid>
</Window>

टिप्पणियां आमतौर पर XAML फ़ाइलों में शामिल नहीं होती हैं, जो मुझे लगता है कि एक गलती है। मैंने इस परियोजना की सभी XAML फ़ाइलों में कुछ टिप्पणियां जोड़ी हैं। मैं यह नहीं कहता कि वे अब तक की सबसे अच्छी टिप्पणियाँ हैं, लेकिन वे कम से कम यह दर्शाते हैं कि कैसे एक टिप्पणी को स्वरूपित किया जाना चाहिए। ध्यान दें कि XAML में नेस्टेड टिप्पणियों की अनुमति नहीं है।

XAML और F # में संवाद बॉक्स बनाएँ

स्पाइरोग्राफ पैरामीटर के लिए XAML फ़ाइल नीचे है। इसमें स्पाइरोग्राफ पैरामीटर के लिए तीन टेक्स्ट बॉक्स और रंग के लिए तीन रेडियो बटन का एक समूह शामिल है। जब हम रेडियो बटन को एक ही समूह का नाम देते हैं - जैसा कि हमारे यहाँ है - जब एक का चयन किया जाता है तो WPF ऑन / ऑफ स्विच को हैंडल करता है।

<!-- This first part is boilerplate, except for the title, height and width.
     Note that some fussing with alignment and margins may be required to get
     the box looking the way you want it. -->
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Parameters" Height="200" Width="250">
    <!-- Here we define a layout of 3 rows and 2 columns below the title bar -->
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <!-- Define a label and a text box for the first three rows. Top row is
             the integer radius of the outer circle -->
        <StackPanel Orientation="Horizontal" Grid.Column="0" Grid.Row="0" 
                    Grid.ColumnSpan="2">
            <Label VerticalAlignment="Top" Margin="5,6,0,1" Content="R: Outer" 
                   Height="24" Width='65'/>
            <TextBox x:Name="radiusR"  Margin="0,0,0,0.5" Width="120" 
                     VerticalAlignment="Bottom" Height="20">Integer</TextBox>
        </StackPanel>
        <!-- This defines a label and text box for the integer radius of the
             inner circle -->
        <StackPanel Orientation="Horizontal" Grid.Column="0" Grid.Row="1" 
                    Grid.ColumnSpan="2">
            <Label VerticalAlignment="Top" Margin="5,6,0,1" Content="r: Inner" 
                   Height="24" Width='65'/>
            <TextBox x:Name="radiusr"  Margin="0,0,0,0.5" Width="120" 
                     VerticalAlignment="Bottom" Height="20" Text="Integer"/>
        </StackPanel>
        <!-- This defines a label and text box for the float ratio of the inner
             circle radius at which the pen is positioned -->
        <StackPanel Orientation="Horizontal" Grid.Column="0" Grid.Row="2" 
                    Grid.ColumnSpan="2">
            <Label VerticalAlignment="Top" Margin="5,6,0,1" Content="l: Ratio" 
                   Height="24" Width='65'/>
            <TextBox x:Name="ratiol"  Margin="0,0,0,1" Width="120" 
                     VerticalAlignment="Bottom" Height="20" Text="Float"/>
        </StackPanel>
        <!-- This defines a radio button group to select color -->
        <StackPanel Orientation="Horizontal" Grid.Column="0" Grid.Row="3" 
                    Grid.ColumnSpan="2">
            <Label VerticalAlignment="Top" Margin="5,6,4,5.333" Content="Color" 
                   Height="24"/>
            <RadioButton x:Name="buttonBlue" Content="Blue" GroupName="Color" 
                         HorizontalAlignment="Left"  VerticalAlignment="Top"
                         Click="buttonBlueClick"
                         Margin="5,13,11,3.5" Height="17"/>
            <RadioButton x:Name="buttonRed"  Content="Red"  GroupName="Color" 
                         HorizontalAlignment="Left" VerticalAlignment="Top"
                         Click="buttonRedClick"
                         Margin="5,13,5,3.5" Height="17" />
            <RadioButton x:Name="buttonRandom"  Content="Random"  
                         GroupName="Color" Click="buttonRandomClick"
                         HorizontalAlignment="Left" VerticalAlignment="Top"
                         Margin="5,13,5,3.5" Height="17" />
        </StackPanel>
        <!-- These are the standard OK/Cancel buttons -->
        <Button Grid.Row="4" Grid.Column="0" Name="okButton" 
                Click="okButton_Click" IsDefault="True">OK</Button>
        <Button Grid.Row="4" Grid.Column="1" Name="cancelButton" 
                IsCancel="True">Cancel</Button>
    </Grid>
</Window>

अब हम Dialog.Box के लिए कोड जोड़ते हैं। कन्वेंशन द्वारा, बाकी प्रोग्राम के साथ संवाद बॉक्स के इंटरफ़ेस को संभालने के लिए उपयोग किए जाने वाले कोड का नाम XXX.xaml.fs है, जहां संबंधित XAML फ़ाइल का नाम XXX.xaml है।

namespace Spirograph

open System.Windows.Controls

type DialogBox(app: App, model: Model, win: MainWindowXaml) as this =
  inherit DialogBoxXaml()

  let myApp   = app
  let myModel = model
  let myWin   = win
  
  // These are the default parameters for the spirograph, changed by this dialog
  // box
  let mutable myR = 220                 // outer circle radius
  let mutable myr = 65                  // inner circle radius
  let mutable myl = 0.8                 // pen position relative to inner circle
  let mutable myColor = MBlue           // pen color

  // These are the dialog box controls. They are initialized when the dialog box
  // is loaded in the whenLoaded function below.
  let mutable RBox: TextBox = null
  let mutable rBox: TextBox = null
  let mutable lBox: TextBox = null

  let mutable blueButton: RadioButton   = null
  let mutable redButton: RadioButton    = null
  let mutable randomButton: RadioButton = null

  // Call this functions to enable or disable parameter input depending on the
  // state of the randomButton. This is a () -> () function to keep it from
  // being executed before we have loaded the dialog box below and found the
  // values of TextBoxes and RadioButtons.
  let enableParameterFields(b: bool) = 
    RBox.IsEnabled <- b
    rBox.IsEnabled <- b
    lBox.IsEnabled <- b

  let whenLoaded _ =
    // Load and initialize text boxes and radio buttons to the current values in 
    // the model. These are changed only if the OK button is clicked, which is 
    // handled below. Also, if the color is Random, we disable the parameter
    // fields.
    RBox <- this.FindName("radiusR") :?> TextBox
    rBox <- this.FindName("radiusr") :?> TextBox
    lBox <- this.FindName("ratiol")  :?> TextBox

    blueButton   <- this.FindName("buttonBlue")   :?> RadioButton
    redButton    <- this.FindName("buttonRed")    :?> RadioButton
    randomButton <- this.FindName("buttonRandom") :?> RadioButton

    RBox.Text <- myModel.MyR.ToString()
    rBox.Text <- myModel.Myr.ToString()
    lBox.Text <- myModel.Myl.ToString()

    myR <- myModel.MyR
    myr <- myModel.Myr
    myl <- myModel.Myl
  
    blueButton.IsChecked   <- new System.Nullable<bool>(myModel.MyColor = MBlue)
    redButton.IsChecked    <- new System.Nullable<bool>(myModel.MyColor = MRed)
    randomButton.IsChecked <- new System.Nullable<bool>(myModel.MyColor = MRandom)
   
    myColor <- myModel.MyColor
    enableParameterFields(not (myColor = MRandom))

  let whenClosing _ =
    // Show the actual spirograph parameters in a message box at close. Note the 
    // \n in the sprintf gives us a linebreak in the MessageBox. This is mainly
    // for debugging, and it can be deleted.
    let s = sprintf "R = %A\nr = %A\nl = %A\nColor = %A" 
                    myModel.MyR myModel.Myr myModel.Myl myModel.MyColor
    System.Windows.MessageBox.Show(s, "Spirograph") |> ignore
    ()
  
  let whenClosed _ =
    () 
  
  do 
    this.Loaded.Add whenLoaded
    this.Closing.Add whenClosing
    this.Closed.Add whenClosed

  override this.buttonBlueClick(sender: obj, 
                                eArgs: System.Windows.RoutedEventArgs) =
    myColor <- MBlue
    enableParameterFields(true)
    () 
  
  override this.buttonRedClick(sender: obj, 
                               eArgs: System.Windows.RoutedEventArgs) =
    myColor <- MRed      
    enableParameterFields(true)
    () 
  
  override this.buttonRandomClick(sender: obj, 
                                  eArgs: System.Windows.RoutedEventArgs) =
    myColor <- MRandom
    enableParameterFields(false)
    () 
  
  override this.okButton_Click(sender: obj,
                               eArgs: System.Windows.RoutedEventArgs) =
    // Only change the spirograph parameters in the model if we hit OK in the 
    // dialog box.
    if myColor = MRandom
    then myModel.Randomize
    else myR <- RBox.Text |> int
         myr <- rBox.Text |> int
         myl <- lBox.Text |> float

         myModel.MyR   <- myR
         myModel.Myr   <- myr
         myModel.Myl   <- myl
         model.MyColor <- myColor

    // Note that setting the DialogResult to nullable true is essential to get
    // the OK button to work.
    this.DialogResult <- new System.Nullable<bool> true         
    () 

यहाँ बहुत से कोड यह सुनिश्चित करने के लिए समर्पित हैं कि Spirograph.fs में स्पिरोग्राफ पैरामीटर इस संवाद बॉक्स में दिखाए गए से मेल खाते हैं। ध्यान दें कि कोई त्रुटि जाँच नहीं है: यदि आप शीर्ष दो पैरामीटर फ़ील्ड में अपेक्षित पूर्णांक के लिए एक अस्थायी बिंदु दर्ज करते हैं, तो प्रोग्राम क्रैश हो जाएगा। इसलिए, कृपया अपने प्रयास में त्रुटि जाँच जोड़ें।

यह भी ध्यान दें कि पैरामीटर इनपुट फ़ील्ड रेडियो बटन में रैंडम रंग के साथ अक्षम हैं। यह केवल यह दिखाने के लिए है कि यह कैसे किया जा सकता है।

संवाद बॉक्स और प्रोग्राम के बीच डेटा को आगे और पीछे खिसकाने के लिए मैं System.Windows.Element.FindName () का उपयोग उपयुक्त नियंत्रण को खोजने के लिए करता हूं, इसे उस नियंत्रण पर कास्ट करें जो इसे होना चाहिए, और फिर संबंधित सेटिंग्स से प्राप्त करें नियंत्रण। अधिकांश अन्य उदाहरण कार्यक्रम डेटा बाइंडिंग का उपयोग करते हैं। मैंने दो कारणों से नहीं किया: पहला, मैं यह पता नहीं लगा सका कि इसे कैसे काम करना है, और दूसरा, जब यह काम नहीं करता तो मुझे किसी भी तरह का कोई त्रुटि संदेश नहीं मिला। हो सकता है कि जो कोई StackOverflow पर इसे देखे, वह मुझे बता सकता है कि NuGet पैकेजों के पूरे नए सेट को शामिल किए बिना डेटा बाइंडिंग का उपयोग कैसे करें।

MainWindow.xaml के लिए कोड जोड़ें

namespace Spirograph

type MainWindow(app: App, model: Model) as this =
  inherit MainWindowXaml()

  let myApp   = app
  let myModel = model
  
  let whenLoaded _ =
    ()
  
  let whenClosing _ =
    ()
  
  let whenClosed _ =
    () 
  
  let menuExitHandler _ = 
    System.Windows.MessageBox.Show("Good-bye", "Spirograph") |> ignore
    myApp.Shutdown()
    () 
  
  let menuParametersHandler _ = 
    let myParametersDialog = new DialogBox(myApp, myModel, this)
    myParametersDialog.Topmost <- true
    let bResult = myParametersDialog.ShowDialog()
    myModel.DrawSpirograph
    () 
  
  let menuDrawHandler _ = 
    if myModel.MyColor = MRandom then myModel.Randomize
    myModel.DrawSpirograph
    () 
  
  let menuAboutHandler _ = 
    System.Windows.MessageBox.Show("F#/WPF Menus & Dialogs", "Spirograph") 
    |> ignore
    () 
  
  do          
    this.Loaded.Add whenLoaded
    this.Closing.Add whenClosing
    this.Closed.Add whenClosed
    this.menuExit.Click.Add menuExitHandler
    this.menuParameters.Click.Add menuParametersHandler
    this.menuDraw.Click.Add menuDrawHandler
    this.menuAbout.Click.Add menuAboutHandler

यहां बहुत कुछ नहीं चल रहा है: हम आवश्यकता पड़ने पर पैरामीटर्स डायलॉग बॉक्स खोलते हैं और हमारे पास स्पिरोग्राफ को फिर से परिभाषित करने का विकल्प है जो कि वर्तमान पैरामीटर हैं।

सब कुछ एक साथ टाई करने के लिए App.xaml और App.xaml.fs जोड़ें

<!-- All boilerplate for now -->
<Application 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"               
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">      
    <Application.Resources>      
    </Application.Resources>  
</Application>

यहाँ पीछे कोड है:

namespace Spirograph

open System  
open System.Windows 
open System.Windows.Controls

module Main = 
  [<STAThread; EntryPoint>]
  let main _ =
    // Create the app and the model with the "business logic", then create the
    // main window and link its Canvas to the model so the model can access it.
    // The main window is linked to the app in the Run() command in the last line.
    let app = App()
    let model = new Model()
    let mainWindow = new MainWindow(app, model) 
    model.MyCanvas <- (mainWindow.FindName("myCanvas") :?> Canvas)         
    
    // Make sure the window is on top, and set its size to 2/3 of the dimensions 
    // of the screen.
    mainWindow.Topmost <- true
    mainWindow.Height  <- 
      (System.Windows.SystemParameters.PrimaryScreenHeight * 0.67)
    mainWindow.Width   <- 
      (System.Windows.SystemParameters.PrimaryScreenWidth * 0.67) 
    
    app.Run(mainWindow) // Returns application's exit code.

App.xaml यहां सभी बॉयलरप्लेट है, मुख्य रूप से यह दिखाने के लिए कि एप्लिकेशन संसाधन, जैसे आइकन, ग्राफिक्स, या बाहरी फाइलें - घोषित की जा सकती हैं। साथी App.xaml.fs मॉडल और MainWindow को एक साथ खींचता है, MainWindow को उपलब्ध स्क्रीन आकार के दो-तिहाई आकार देता है, और इसे चलाता है।

जब आप इसे बनाते हैं, तो यह सुनिश्चित करना याद रखें कि प्रत्येक xaml फ़ाइल के लिए बिल्ड संपत्ति संसाधन पर सेट है। फिर आप डिबगर के माध्यम से चला सकते हैं या एक exe फ़ाइल को संकलित कर सकते हैं। ध्यान दें कि आप इसे F # इंटरप्रेटर का उपयोग करके नहीं चला सकते हैं: FsXaml पैकेज और दुभाषिया असंगत हैं।

ये लो। मुझे आशा है कि आप इसे अपने स्वयं के अनुप्रयोगों के लिए एक प्रारंभिक बिंदु के रूप में उपयोग कर सकते हैं, और ऐसा करने में आप यहां दिखाए गए से परे अपने ज्ञान को बढ़ा सकते हैं। किसी भी टिप्पणी और सुझाव की सराहना की जाएगी।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow