基于托管的C++来使用WPF - Using WPF with Managed C++

Posted by Zeeshan Amjad

This article was originally published on August 12th, 2009

1. Introduction

The purpose of this article is two folds. At the first half we discuss what WPF is. In addition we studied why and how to program WPF using Managed C++ and high level overview of WPF architecture. Latter we scratch the surface of Loan Amortization with one working example of Loan Amortization in WPF using C++.

2. What is WPF?

Before going to study the WPF one might ask a question that what is WPF? WPF is abbreviation of "Window Presentation Foundation". It is a next generation presentation system for building window client application that can be run stand alone as well as in a Web Browser (i.e. XBAP Application). WPF is based on .Net environment, it means it is a managed code and theoretically can be written with any .Net based language such as Visual C#, VB.Net and Managed C++. WPF introduced with .Net 3.0 with few other important technologies such as Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF), but here we are going to study only WPF.

WPF is the latest Microsoft technologies to create user interface. It was introduced with .Net 3.0 and then improved in .Net 3.5 and .Net 4.0 (Beta as of now). It does not depend on Windows Standard control; it draws everything from DirectX technology and takes full advantage of 3D graphics and hardware accelerator if available.

Most of the programmer thought that WPF is a feature of Visual C# and VB.Net can be done only in these languages. Although writing WPF programs in these languages are quite easy and fun, but it is not limited to only this. WPF is in fact a feature of .Net introduced with its version 3.5; therefore technically any .Net language can use it.

If this is a case then why there are so many WPF samples written only in C# and VB.Net codes even in MSDN? The best answer might be because of XAML. When using C# or VB.Net then we can take full advantage of XAML, which is not available in VC++.Net. It means when you are trying to write WPF code in Managed C++, then you are on your own and have to write code for everything. It may be a daunting task but not impossible and in fact there are few samples available with Microsoft SDK such as PlotPanel, RadialPanel, CustomPanel etc.

2.1. Why Managed C++ for WPF?

Next question is why should we use Managed C++ in Visual C++ to write WPF application when we can do the same thing in C# or VB.Net with XAML? There can be different reasons for it.

  • You lots of code base written in VC++ unmanaged code and it is not possible to rewrite everything in C#. You want to take advantage of both managed and unmanaged code in your project, such as using MFC document view architecture with rich user interface of WPF without creating any new DLL in C#.
  • Portion of your programs should be optimized for speed and for performance reason you write unmanaged code for it. WPF internally used the same technique for performance reason to call DirectX.
  • You want to hide the implementation of some portion of your program and or algorithm so no one can reverse engineer and write it as unmanaged code so no one can reverse engineer your code using ildasm.
  • Just for fun.

2.2. WPF Programming in VC++

To create simplest WPF program using Managed C++, you have to include reference of .Net components named windowsbase.dll, presentationcore.dll and presentationframeworkd.dll. In addition the program must be compiled using /clr switch because it is a managed code. Here is a diagram to show one project that has added references of these three DLL. To add the reference, right click on the project in the Solution Explorer tree and select "Reference..." from there.

If we want to create a simple windows based program then it would be something like this.

#include <windows.h>
using namespace System::Windows; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmd, int nCmd)
{
MessageBox::Show("Hello World");
}

This program does nothing more than simply display one message box. We can further shorten the program by using main instead of WinMain and avoid including windows.h header file altogether, but in that case we will see the black console window behind the message box.

If we want to make something more useful and interesting then we have to create objects of at least two classes Window and Application. But remember there can be only one object of Application class in the whole program. Here is the simplest program to show the usage of Window and Application class.

#include <windows.h>
using namespace System;
using namespace System::Windows; [STAThread]
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmd, int nCmd)
{
Window^ win = gcnew Window();
win->Title = "Hello World"; Application^ app = gcnew Application();
app->Run(win);
}

The output of this program is a blank window with a title "Hello World". Here Application class is used to start the WPF application, manage the state of application and application level variables and information, but there is no output of it. It is Windows class that is responsible to draw window on the screen. Run method should be the last method call in the program, because this method won't return until the program close. Return value of Run method is application exit code return to the operating system.

It is not necessary to pass the window object as a parameter in the run function of application class. We can call Run function without any parameter, but if we call the Run function without any parameter then we have to call the Show or ShowDilaog function of Window class before calling the Run. Difference between Show and ShowDialog is Show display the model dialog, on the other hand ShowDialog display the modeless dialog. For our simple application it doesn't make any difference.

You can inherit your classes from Window and Application classes to store some application specific or window specific information. But remember you class must be inherited using the "ref" keyword and use "gcnew" keyword to create an instance of it on managed heap. Here is a simple program to show the usage of user inherited Window and Application classes.

#include <windows.h>
using namespace System;
using namespace System::Windows; public ref class MyWindow : public Window
{
public:
MyWindow()
{
Title = "Hello World";
}
}; public ref class MyApplication : public Application
{
}; [STAThread]
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmd, int nCmd)
{
MyWindow^ win = gcnew MyWindow(); MyApplication^ app = gcnew MyApplication();
app->Run(win);
}

Output of this program is same as the previous one. In this program we can store all the application specific information in MyApplication class and Window specific information in MyWindow class. For example we set the title of the window in the constructor rather than in main after creating the object of it. We can also set other properties of window such as its back ground color, size, etc in the same place i.e. constructor.

These classes and their usages looks quite familiar with MFC. In MFC based application we also need object of two classes named CWinApp and CWnd. Similarly we create only one object of CWinApp based class and call the run method of CWinApp.

2.3. WPF Class Hierarchy

As we have seen before that to make smallest WPF application that display its own window we have to create objects of at least two classes named Window and Application. Before going further let's take a look at these two classes in little bit more detail. Here is a class diagram to show the inheritance chain for Application and Window class.

2.4. High Level Architecture of WPF

If we see the higher level architecture of WPF then the best approach is to write code in any .Net language weather it is C#, VB or C++ rather than using XAML. If we write code in any programming language then we understand about WPF classes in more detail.

When we write WPF program then it internally uses DirectX to draw everything including all controls. All WPF calls are passed to DirectX via Media Integration Layer. For performance reason Media Integration Layer is written in unmanaged code. Here is an overall diagram of WPF application.

There are few other layers which are not shown here. Such as taking the input from user is responsibility of user32.dll. In addition WPF is written in .Net based language, it means WPF application uses .Net language and run on common language runtime not shown in this diagram.

2.4.1. WPF Layer

Now let's dig down little bit more and try to explore these layers in little bit more detail. First layer in this stack is your application code that is of course a managed code written in any .Net language. In case of Managed C++ it can be a mixture of managed and unmanaged code compiled with /clr switch.

Second layer of the stack is WPF layer. It is composed by three DLLs named WindowsBase.dll, PresentationCore.dll and PresentationFramework.dll. All WPF programs whether written in C++, C# or VB.Net has to include the reference of these DLLs.

The first component in WPF layer is WindowsBase.DLL. This DLL provides some very basic level functionality to the WPF which can be used in other applications too. This DLL provides the support of threading and dependency property, which we are going to study in more detail in the following sections.

Second component PresentationCore.DLL provides the basic building block for WPF framework. From the design prospect WPF divides its classes in two groups, the core and framework. This DLL has some core functionality of WPF classes such as Visual to draw something and UIElement, basic building block that WPF Framework uses.

PresentationFrameWork provides the support of WPF framework. This DLL has support for layout, event handling, controls, animation and almost everything WPF has. When writing a WPF program, we usually use the classes defined in this component. All the controls such as Label, TextBlock, Button, Menu etc are defined in this component.

2.4.2. Media Integration Layer

The other layer of WPF program is Media Integration Layer. It is written in unmanaged code for performance reason and directly interfaces with DirectX. This layer has two important component milcore.dll and windowscodecs.dll. Milcore.dll is responsible for give 2D and 3D support and windowscodecs.dll is support different imaging support.

Here is a combine diagram to show all the major component of WPF application. This diagram shows all major components of WPF application. Please note that in this diagram we only focus on WPF and DirectX, because WPF internally uses DirectX to draw everything on the screen. But there are other components also involved in any WPF or any windows based program. It still uses User32.dll to get user input and operating system kernel DLL and device driver to hardware interface. In addition it is also understood that WPF code also runs in managed environment. It means WPF layer is based on Common run time environment. To make things simple, we only focus those elements in this diagram, which are part of WPF.

3. Time Value of Money

The time value of money is a very basic concept in financial engineering and lots of other concepts are built on it. Here we study the value of money with respect to time (i.e. how much the value of money would be change from time). The value of money changes either from time or from interest rates. If you assumed that the interest rate is same during the whole time period, then the only factor that can change the value of money is time.

3.1. Compound Interest

Compound interest is the most common method of calculating the interest in real life. The difference between simple interest and compound interest is that in simple interest you will get profit only in the first year's value of the money; however in compound interest you will get money on every year's value of the money. For example if you have $1000 and your bank will give you 10% interest rate then after one year the value of your money will become $1100. In case of simple interest you will still get the second year's profit based on the first year value, $1000. In the case of compound interest, you will get profit on $1100 for the second year.

In compound interest you will get profit on every year's value not only the first year value therefore the value of money will increase more rapidly in compound interest than simple interest. We show the change of the value of money in ten years in the given table.

Demonstrating the same thing in the form of graph shows a curve as can be seen in the figure.

The easiest way to calculate the compound interest is that first convert the interest in one point form then multiplies it with original value.

For example to convert 12.5% into one point form, first divide it by 100 then add one in the result. It will become 1.125. If we multiply the original amount with this then we will get the value of money after one year. To get the value of money after two year, we will multiply the original value with 1.125 twice.

Mathematically we can write this in this way

3.2. Period Compound Interest

It is not uncommon to get profit more than once per year, such as after every six months, monthly etc. This is known as Periodic Compound Interest. In that case we simply divide the interest rate with the number of times we get profit in the year. For example, if you are getting profit with 10% interest rate annually and you want to get profit after every six months then your interest rate will be 5% not 10% because you are getting profit twice per year.

Let's take a look this with one example. Suppose you invest $1500 in a bank with 6% interest rate. We have already seen the method to calculate the compound interest annually. Here is the table to show the compound interest calculated annually for 5 years

Here is the table to show the interest calculated bi annually.

This table shows that we will get more profit with monthly than annually. It is even more than bi-annually.

In other words the higher the number of times we get the profit, the higher the profit we get at the end of the year. Here is the mathematical formula to calculate the profit taken more than once.

3.3. Annuity

In financial engineering annuity is a concept of taking or giving some predefined money at some specified time, for example if you pay the installment of your car or withdraw some specific money from the bank every month. The important thing about annuity is that the amount should be same and periodic.

Suppose you deposit some money in your bank every year. If you are not getting any profit then after some years the value of your money will be the multiple of the number of year. For example if you deposit $1000 in a bank for 5 years then you will have $5000 after 5 years.

As we know that the value of money changes with respect to time and that change is depend on the interest rate. Let's suppose we are getting 10% interest rate from the bank. In this case we won't get any profit at the end of first year, because we deposited that money at the end of year and that money was not in the bank for the whole year. At the end of second year, we will get profit on the first year money because that money was in the bank for whole year and we won't get any profit of the money which we deposited at the end of second year. Similarly at the end of third year we will get the profit of first two years money because that money was in the bank for the whole year.

In other words we can say that if we deposit "x" amount in a bank for "n" years then we won't get any profit on the money which we deposit at the last year. We will get only one year profit on the money that we will deposit at "n-1" year because that money will be in the bank for only one year. The money we will deposit at "n-1" year, we will get 2 years profit, because that money will be in the bank for 2 years. In the same way we will get the "n-1" year profit on the first year money because that money will be in the bank for "n-1" years. Now the value of our annuity will be the sum of all of these values. In this table we show the profit on $1000 with 10% interest rate for different 1 year to 5 years.

It means this will be the value of our money after every year.

If we make a graph of this then it will be a curve.

Mathematically we can write the same thing this way

This is a geometric series. Using the geometric series formula for sum, it will become something like this.

3.4. Annuity with more than one payment per year

In real life most of our payments are monthly, biannually or quarterly basis not on annually basis. In this section we are going to study what will be the effect of this on annuity when we have more than one payment in the year. We have already study the concept of more than one payment during the study of time value of money.

If we have more than one payment per year then we simply divide the interest rate by the number of payments per year because interest rate is usually given in annual interest rate form. In addition we multiply the number of years by the number of payments per year, because now we are getting (or paying) more payments.

We already know how to calculate the future value of annuity when there is only one payment per year. Here is the modified formula to calculate the future value of annuity when there is more than one payment per year.

3.5. Loan Amortization

If we take a loan then we usually pay it easily monthly installments. This is in fact application of annuity with more than one payment per year. To calculate the monthly payment of the loan first we have to calculate the present value of the annuity.

We already studied how to calculate future value of money using this formula.

If we just modify this formula little bit then we can calculate the present value of money. Here is a formula to calculate the present value of the money.

To calculate the present value of annuity, we have to calculate the present value of all the money we deposit (or withdraw) into a bank and then sum it. Mathematically we can write it in this way.

This is again a geometric series. Here is the sum of this series using geometric series formula.

If there is more than one payment per year then we have to divide the interest rate by the total number of payments per year and multiply total number of years. Here is a modified formula to calculate the present value of annuity if there is more than one payment per year.

If we already know the present value of annuity (i.e. amount of loan we are going to take) interest rate and the payment method (i.e. weather it is going to be monthly, quarterly, yearly etc) then we can easily rearrange this formula to calculate the payment amount of the loan. Here is the formula to calculate the payment amount of loan. For monthly payment the value of n should be 12, i.e. 12 payments per year.

Let's suppose e get $5000 loan from a bank with 12.5% interest rate. Just to keep our calculation small we assumed that we are going to pay off the loan in one year, so we will have only 12 payments.

By using the above formula our monthly payment would be $445.4143. Now the question is how much money of this payment is going to pay the interest and how much will be used to paid off the principle amount. We can calculate the interest on this money using time value of money formula.

FV = 5052.08333

The interest after one month will be

Interest = Future Value - Present Value
Interest = 5052.08333 - 5000
Interest = 52.08333

The remaining amount of your payment will be the principle amount.

Principle = Payment - Interest
Principle = 455.4143 - 52.08333
Principle = 393.331

Now our new amount will be

Amount = 5000 - 393.331
Amount = 4606.669202

And the second month's interest will be calculated on this new amount. Similarly we can calculate the interest part and principle amount part of each payment for every payment. Here we showed the same thing in tabular form, here 5th and 6th columns shows the interest part and principle amount part of the monthly payment respectively.

If we take a look at this table carefully then we can observe that the amount of interest rate will decrease after every month. In first month we pay $52.08 interest, in second month it became $47.98, in third month it became $43.84 and in last month we pay only $4.59 interest. This is because the principle amount decrease every month, and we already know that if interest rate and time is constant then the only factor to change the value of interest is original amount. Lower the amount, lower the interest rate is.

On the other hand the amount of principle amount will increase from every previous month. The reason of this phenomenon is very obvious; because the value of monthly payment is same and interest rate decrease every month then the remaining amount will increase every month. In other words, as month goes on, the value of your principle amount will decrease more rapidly.

We can show the same thing in this graph. Here we displayed two graphs; first one shows the interest part of the monthly payment and other shows the principle amount part of the payment.

This graph shows the value of interest we pay each month to pay off the loan. This graph is strictly decreasing; means the value of interest will decrease every month. It looks like a straight line, but in fact this is a curve. There are twelve payments in this example, but if we have an example of 30 years home mortgage, i.e. 360 payments then we can see this easily.

What is the meaning of curve line instead of straight line? We have already seen that the amount of interest decrease, but the ratio of reduction of interest rate is not same during every month. The ratio of decreasing the interest part will increase in each passing month. It means the interest of interest we pay each month will reduce more rapidly than same every month.

In the above example if we take a difference between the interest part of first two payments then it would be

Difference

1

 = 52.08333 - 47.9861Difference

1

 = 4.097198

Similarly the difference between the interest part of the second month and third month would be

Difference

2

 = 47.9861 - 43.8462
Difference

2

 = 4.139877

We can verify that the difference between the interest parts of two consecutive payments will always increase.

The situation of principle amount part is no different. Let's take a look at the principle amount part of the payment. Here is the graph of principle amount part of the payment.

This graph is very much similar to the interest rate part of the payment graph. The only difference is the direction. This is also a curve just like the interest part graph but here we can see the amount of principle amount is increasing. The difference between any two consecutive principle amount parts will be exactly same as we have seen in the interest graph, but with a negative sign. Reason behind this is very simple, we have fixed monthly payment every months and it contains only two parts, interest and principle; so whatever value is excluded from one portion will automatically be included into other portion.

For every payment there are two parts of payment the interest part and principle amount part.

PMT = INTEREST + PRINCIPLE

We have different value of interest and principle amount in each payment. In general we can represent it in such way

PMTi = Ri + Pi

We already saw that the principle amount will reduce with each payment. It depends on the interest calculated in the previous principle amount. Here is the formula to calculate the remaining principle amount after a specified amount of time, say after "n" months.

This is again a geometric series. We can calculate the sum of it using geometric series formula. The value of Principle amount after nth payment would be

Similarly if we want to calculate the interest part of any specific period then first we have to calculate the principle amount remaining at that time and multiply it with interest rate. Here is the formula to calculate the interest part of any specific payment.

Rn = An * r

After solving this geometric series we get the formula to calculate the interest part of any particular payment. Here is the formula to calculate the interest part of any payment.

Once we calculated the interest part then principle amount part is very easy to calculate. Any payment has only two parts principle amount and interest, if we already calculate the interest part then we can subtract it from the payment to get the principle amount part. Here is the formula to calculate the principle amount part of the payment.

PMTi = Ri + Pi

4. Loan Amortization Application in WPF

We have all of our required formulae so we can write small functions to perform these calculations. Here are the auxiliary functions to calculate remaining balance, interest part and principle amount part of any particular payment.

// Calculate the remaining balance at particular payment
double PaymentWindow::CalculateBalance(int month)
{
double interestTerm = Math::Pow((1 + interestRate), month);
double totalInterest = principle * interestTerm;
double totalPaid = payment * (interestTerm - 1) / interestRate;
return totalInterest - totalPaid;
} // Calculate the Interest part of any particular payment
double PaymentWindow::CalculateInterestPart(int month)
{
double interestTerm = Math::Pow((1 + interestRate), (month - 1));
double totalInterest = principle * interestTerm;
double totalPaid = payment * (interestTerm - 1) / interestRate;
return (totalInterest - totalPaid) * interestRate;
} // Calculate the principle part of any particular payment
double PaymentWindow::CalculatePrinciple(int month)
{
return payment - CalculateInterestPart(month);
}

We need to take four inputs such as total payment, interest rate, total number of payment per year, total number of years and type of payments. We need auxiliary class to store information about all payments and export these as properties so we can use this in list control. Here is our auxiliary class.

public ref class PaymentInfo
{
private:
int paymentNo;
double payment;
double principle;
double interest;
double balance; public:
property int PaymentNo
{
int get()
{ return paymentNo; } void set(int value)
{ paymentNo = value; }
} property double Payment
{
double get()
{ return payment; } void set(double value)
{ payment = value; }
} property double Principle
{
double get()
{ return principle; } void set(double value)
{ principle = value; }
} property double Interest
{
double get()
{ return interest; } void set(double value)
{ interest = value; }
} property double Balance
{
double get()
{ return balance; } void set(double value)
{ balance = value; }
}
};

Here is an auxiliary function to calculate the interest part, principle amount part and remaining balance after each payment and add those items in the list control.

// Calculate the complete amortization schedule and fill the list control
void PaymentWindow::CalculatePayment()
{
Title = L"Amortizatin Schedule for " + Convert::ToString(totalpayments) + " Payments"; // calculate interest term
double interestTerm = Math::Pow((1 + interestRate), totalpayments); // calculate payment
payment = (principle * interestRate) / (1 - (1 / interestTerm)); for (int iIndex = 1; iIndex <= totalpayments; ++iIndex)
{
PaymentInfo^ paymentInfo = gcnew PaymentInfo();
paymentInfo->PaymentNo = iIndex;
paymentInfo->Balance = CalculateBalance(iIndex);
paymentInfo->Payment = payment;
paymentInfo->Interest = CalculateInterestPart(iIndex);
paymentInfo->Principle = CalculatePrinciple(iIndex); lstView->Items->Add(paymentInfo);
}
}

Here is the output of the program.

This program is not restricted to monthly payments only. We can select different payment methods such as Monthly, Quarterly, Bi-Yearly, Yearly or daily. There is one enum defined for the payment selection.

enum PaymentMethod
{
NotSelected = 0,
Monthly,
Quartly,
BiYearly,
Yearly,
Daily
};

Here is the output of the amortization schedule. This dialog display the monthly payment, the total amount paid over time and the interest and principle amount part of every payment.

Reference:

https://www.codeguru.com/cpp/cpp/cpp_managed/general/article.php/c16355/Using-WPF-with-Managed-C.htm

基于托管的C++来使用WPF - Using WPF with Managed C++的更多相关文章

  1. 重复造轮子系列——基于FastReport设计打印模板实现桌面端WPF套打和商超POS高度自适应小票打印

    重复造轮子系列——基于FastReport设计打印模板实现桌面端WPF套打和商超POS高度自适应小票打印 一.引言 桌面端系统经常需要对接各种硬件设备,比如扫描器.读卡器.打印机等. 这里介绍下桌面端 ...

  2. 【WPF】WPF截屏

    原文:[WPF]WPF截屏 引言 .NET的截图控件在网上流传得不多啊,难得发现一个精品截图控件( 传送门),但是无奈是winform的.后来又找到一个周银辉做的WPF截图(继续传送门),发现截屏是实 ...

  3. 【WPF】wpf用MultiBinding解决Converter需要动态传参的问题,以Button为例

    原文:[WPF]wpf用MultiBinding解决Converter需要动态传参的问题,以Button为例       用Binding并通过Converter转换的时候,可能偶尔会遇到传参的问题, ...

  4. WPF编程-WPF体系结构

    WPF简介 Windows Presentation Foundation(WPF)是微软新一代图形系统,运行在.NET Framework 3.0架构下,为用户界面.2D/3D 图形.文档和媒体提供 ...

  5. 【转】【WPF】wpf 图片指针处理

    我一直用GDI+做Winform 的基于指针的图片处理,这次下决心全部移到wpf上(主要是显示布局很方便)采用的图片是2512*3307 的大图 830万像素类库基于WritableBitmapEx ...

  6. 【转】【WPF】WPF绑定用法

    一.简介 为了后面行文顺利,在进入正文之前,我们首先对本文所涉及到的绑定知识进行简单地介绍.该节包含绑定的基本组成以及构建方式. WPF中的绑定完成了绑定源和绑定目标的联动.一个绑定常常由四部分组成: ...

  7. [WPF+Prism]WPF个人集成平台

    前段时间学习了一下Prism,感觉应该找个机会实践一下,而且前段时间,贱内(希望我老婆看不到这篇文章:))让我帮她做个定时提醒的小工具,做好之后感觉以前做了好多自己能用的小工具,如果能够整合到一起,该 ...

  8. 【.NET6+WPF】WPF使用prism框架+Unity IOC容器实现MVVM双向绑定和依赖注入

    前言:在C/S架构上,WPF无疑已经是"桌面一霸"了.在.NET生态环境中,很多小伙伴还在使用Winform开发C/S架构的桌面应用.但是WPF也有很多年的历史了,并且基于MVVM ...

  9. 【WPF】WPF中的List<T>和ObservableCollection<T>

    在WPF中 控件绑定数据源时,数据源建议采用 ObservableCollection<T>集合 ObservableCollection<T> 类:表示一个动态数据集合,在添 ...

随机推荐

  1. Java实现 LeetCode 217 存在重复元素

    217. 存在重复元素 给定一个整数数组,判断是否存在重复元素. 如果任何值在数组中出现至少两次,函数返回 true.如果数组中每个元素都不相同,则返回 false. 示例 1: 输入: [1,2,3 ...

  2. Java中那些烦人的位运算(&,|...)

    & 和 && 相同点: 都表示"与"操作.这里的"与"和数学中的"与或非"中的"与"意义相同,都 ...

  3. Java实现 LeetCode 107 二叉树的层次遍历 II(二)

    107. 二叉树的层次遍历 II 给定一个二叉树,返回其节点值自底向上的层次遍历. (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历) 例如: 给定二叉树 [3,9,20,null,null, ...

  4. Java实现 LeetCode 34 在排序数组中查找元素的第一个和最后一个位置

    在排序数组中查找元素的第一个和最后一个位置 给定一个按照升序排列的整数数组 nums,和一个目标值 target.找出给定目标值在数组中的开始位置和结束位置. 你的算法时间复杂度必须是 O(log n ...

  5. .gitignore文件详细说明

    简介 有些时候,你必须把某些文件放到 Git 工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件.Java编译生成的.class文件.处理这个需求很简单,从不git add它们就可以.但这样 ...

  6. 设计模式系列之建造者模式(Builder Pattern)——复杂对象的组装与创建

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  7. Cypress系列(14)- 环境变量详解

    如果想从头学起Cypress,可以看下面的系列文章哦 https://www.cnblogs.com/poloyy/category/1768839.html 前言 环境变量,其实就是根据环境的变化, ...

  8. Python实现抖音关键词热度搜索小程序(附源码)

    今天给大家带来一个抖音热词小程序,废话不多说,直接上代码 import requests import json import urllib.parse import time ''' python知 ...

  9. Spring AOP 之二:Pointcut注解表达式

    简介 在Spring AOP概述中我们重点注意的是AOP的整体流程和Advice,简化了一些其他的东西,其中就有一些对灵活应用Spring AOP很重要的知识点,例如Pointcut表达式,下面就介绍 ...

  10. C# Winform界面不能适配高DPI的解决方法

    1. 将 Form 的 AutoScaleMode 属性设置为 DPI: 2. 在Program.cs中修改代码 class Program { [STAThread] static void Mai ...