[DEVEXPRESS] How to MailMerge with Image in Winform C#

Xin chào các bạn, hôm nay mình hướng dẫn các bạn cách sử dụng Mail Merge có kèm hình ảnh trên Devexpress C#, Winform.
Dưới đây, là hình ảnh giao diện demo ứng dụng:

[DEVEXPRESS] How to MailMerge with Image in Winform C#

SOURCE CODE:

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Printing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using DevExpress.Office.Services;
using DevExpress.XtraRichEdit;
using DevExpress.XtraRichEdit.API.Native;
using DevExpress.XtraPrinting;
using DevExpress.XtraPrinting.BarCode;
using System.IO;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using static ListBoxTemplate.Form1;

namespace MailmergeBarcode
{
    public partial class DevexpressMailMerge : Form
    {
        BarCodeStreamProvider provider;
        public Employee _employee;

        public DevexpressMailMerge(Employee employee)
        {
            InitializeComponent();
            this._employee = employee;
        }

        void RegisterBarCodeProvider(RichEditDocumentServer server, List<Employee> data)
        {
            IUriStreamService uriService = (IUriStreamService)server.GetService(typeof(IUriStreamService));
            provider = new BarCodeStreamProvider(data);
            uriService.RegisterProvider(provider);
        }

        private void btnMergeOption_Click(object sender, EventArgs e)
        {
            RichEditDocumentServer server = new RichEditDocumentServer();
            
            string appPath = Application.ExecutablePath.Substring(0, Application.ExecutablePath.LastIndexOf("\\"));
            string filestr = appPath + @"\certificate.docx";
            server.LoadDocument(filestr, DocumentFormat.Doc);
            var listDaa = new List<Employee>();
            listDaa.Add(_employee);
         
            RegisterBarCodeProvider(server, listDaa);
            server.Options.MailMerge.DataSource = listDaa;
            server.Options.MailMerge.ViewMergedData = true;
            server.Document.Fields.Update();
            MailMergeOptions myMergeOptions = server.Document.CreateMailMergeOptions();
            myMergeOptions.FirstRecordIndex = 0;
            myMergeOptions.LastRecordIndex = 2;
            myMergeOptions.MergeMode = MergeMode.NewSection;
            server.Document.MailMerge(myMergeOptions, richEditControl2.Document);
        }

        private void DevexpressMailMerge_Load(object sender, EventArgs e)
        {
            btnMergeOption_Click(null, null);
        }
    }
}



public class BarCodeStreamProvider : IUriStreamProvider
{
    const string prefix = "\\img://";
    List<Employee> _sampleData;
    public BarCodeStreamProvider(List<Employee> sampleData)
    {
        _sampleData = sampleData;
    }
    #region IUriStreamProvider Members
    public Stream GetStream(string uri)
    {
        if (!uri.StartsWith(prefix))
            return null;
        string value = uri.Substring(prefix.Length);
        var isExisted = _sampleData.Any(x => x.url == value);
        
        if (!isExisted) {
            return null;
        }
        
         
        return ResizeImageFromLocalUri(Application.StartupPath + "\\" + value);
        

    }

    public MemoryStream ResizeImageFromLocalUri(string uri)
    {
       
        Image originalImage = Image.FromFile(uri);    
        int newWidth = 80;
        int newHeight = (int)((float)originalImage.Height / originalImage.Width * newWidth);     
        Bitmap resizedImage = new Bitmap(newWidth, newHeight);
    
        using (Graphics g = Graphics.FromImage(resizedImage))
        {
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            g.DrawImage(originalImage, 0, 0, newWidth, newHeight);
        }
        MemoryStream memoryStream = new MemoryStream();
        resizedImage.Save(memoryStream, ImageFormat.Jpeg);
        
        originalImage.Dispose();
        resizedImage.Dispose();    
        memoryStream.Position = 0;
       
        return memoryStream;
    }
    #endregion
}

Ở file word template khi các bạn muốn merge hình ảnh vào, chúng ta sử dụng: "INCLUDE PICTURE"
Chi tiết mình có hướng dẫn ở Video dưới đây:

DOWNLOAD SOURCE CODE

on Thứ Ba, 31 tháng 10, 2023 | , | A comment?

[FACEBOOK] How to view deleted messages on Facebook messenger

Chắc hẳn các bạn cũng như mình, có cảm giác khá là "kay" và "khó chịu" khi mà bị bỏ lỡ một tin nhắn nào đó chưa kịp check thì đã bị gỡ rồi đúng không nào?


How to view deleted messages on Facebook messenger

Vậy thì bài viết này Hoàng sẽ cùng mọi người trở thành những cảnh sát chực tin nhắn cùng Nodejs nhé.

Bước 1:
  1. Tạo một project trên firebase và đăng ký tạo firebase realtime database. Có thể xem hướng dẫn tại đây và làm đến Bước 2 là được.
  2. Sau đó vào lại Project Setting sau đó chọn Service Accounts sau đó cuộn xuống chọn Generate new private key thì nó sẽ tải về 1 file private key dạng json. Tuyệt đối không để lộ file này ra ngoài nếu không muốn bị lộ tin nhắn, còn không sợ lộ tin nhắn thì không sao.
Bước 2:
  1. Tải C3c extension để lấy appstate của facebook tại đây
  2. Vì là extension nên chúng ta sẽ cài vào trình duyệt như bình thường thôi
  3. Lưu ý là cần bảo mật tuyệt đối cho appstate này nhé, để tránh mất acc
Bước 3:
  1. Lựa chọn 1 trong 2 phương án sau:
  2. Host app trên Replit
  3. Host app trên điện thoại android (cũ không dùng đến)
  4. Đối với host trên Replit
  5. Ưu điểm là nhanh, chả mất gì, nhưng dung lượng lưu trữ của repl có hạn, cũng như nó hay "ngủ" nên phải dùng các web chuyên ping để "tát" cho nó tỉnh. Có thể dùng Uptimerobot để ping cũng rất ổn.
  6. Đối với host trên điện thoại
  7. Phải kể đến đầu tiên với cái server "nhà làm" này là bảo mật hơn vì Replit vẫn có thể bị hack nếu không cẩn thận. Ngoài ra là dung lượng ROM và RAM của điện thoại nó cũng lớn hơn nên rất mượt. Tuy nhiên nhược điểm rất lớn là nhỡ mất điện (mất wifi) mà lại mất đúng lúc có tin nhắn thu hồi nữa thì ta nói nó kayyy:))
Replit

  1. Tải source code hoặc fork replit của mình về tại đây
  2. Hoặc tải file Unseen-Messenger.zip trên github repo tại đây
  3. Các bạn phải đặc biệt lưu ý khi host trên replit (mình quên nói trong video)

VIDEO HƯỚNG DẪN TỪNG BƯỚC.



Mọi người áp dụng để xem lại những tin nhắn mà crush của mọi người xóa khi nói gì về bạn nhé. Chúc các bạn thành công.

on Thứ Năm, 26 tháng 10, 2023 | , , | A comment?

[BLOGGER] How to create an image CDN with your own domain name for Blogger

Có thể hiểu đơn giản là mình sẽ thay thế tên miền ảnh mặc định của Blogger thành tên miền của mình. CDN viết tắt của Content Delivery Network.


Chào các bạn, lâu lắm rồi mình mới lại viết bài về thủ thuật Blogger bài thủ thuật gần nhất cũng đã hơn 7 tháng rồi đó là bài Tạo khung chứa code có nút Copy và Download Code đẹp cho Blogger. Còn trong bài viết ngày hôm nay mình sẽ hướng dẫn các bạn cách tạo CDN hình ảnh với tên miền riêng cho Blogger, nó có thể hiểu đơn giản là mình sẽ thay thế tên miền ảnh mặc định của Blogger thành tên miền của mình. Đầu tiên mình sẽ cùng tìm hiểu CDN là gì!

CDN là gì?

CDN viết tắt của Content Delivery Network là mạng lưới máy chủ lưu giữ bản sao của các nội dung tĩnh bên trong website và phân phối đến nhiều máy chủ PoP. Mạng lưới máy chủ CDN được đặt ở khắp mọi nơi trên toàn cầu. Từ PoP (Points of Presence), dữ liệu sẽ tiếp tục được gửi đến người dùng cuối. Thông qua CDN, bản sao nội dung trên máy chủ gần nhất sẽ được trả về cho người dùng khi họ truy cập website.

Yêu cầu để thực hiện

Để thực hiện thủ thuật này có 1 yêu cầu cần thiết và duy nhất đó là bạn phải sử dụng Cloudflare để quản lý DNS của domain và trỏ về Blogger.

Cách thay thế tên miền của Blogger thành tên miền riêng

Về cơ bản Cách tạo CDN hình ảnh với tên miền riêng cho Blogger cũng tương tự như Cách tạo Progressive Web App (PWA) cho Blogger/Website các bạn có thể đọc tham khảo thêm. Các bước thực hiện như sau:
Bước 1: Truy cập vào trang quản lý tên miền của Cloudflare.
Bước 2: Tại menu bên trái bạn truy cập vào Worker
[BLOGGER] How to create an image CDN with your own domain name for Blogger
Nếu là lần đầu tiên truy cập bạn hãy chọn Create Worker.
Bước 3: Nếu không bạn hãy chọn Create a Service sau đó đặt tên ví dụ như new-images và chọn tiếp Create service.
[BLOGGER] How to create an image CDN with your own domain name for Blogger

Bước 4: Tiếp theo chọn Quick Edit, xoá bỏ đoạn Script có sẵn và thay thế bằng đoạn Script dưới đây:
const ORIGINS = {
  "new-images.hungprovn.workers.dev": "blogger.googleusercontent.com",
  "www.hung.pro.vn": "blogger.googleusercontent.com",
}

async function handleRequest(request) {
  let url = new URL(request.url)
  // Check if incoming hostname is a key in the ORIGINS object
 if (url.hostname in ORIGINS) {
    const target = ORIGINS[url.hostname]
    url.hostname = target
    // If it is, proxy request to that third party origin
    return await fetch(url.toString().replace('/new-images', ''), request)
  }

}

addEventListener("fetch", event => {
  event.respondWith(handleRequest(event.request))
})

Thay thế new-images.hungprovn.workers.dev bằng URL Worker của bạn và www.hung.pro.vn thay bằng tên miền Blog của bạn.

Bước 5: Nhấp Save and deploy.
Bước 6: Truy cập vào trang Cloudflare của tên miền của bạn như ở trên và tại menu bên trái chọn Workers Routes và chọn Add route. Sau đó nhập thông tin như sau:

Route

Service

Environment

https://*.hung.pro.vn/images/*

images

production

 

Nhớ thay hung.pro.vn thành tên miền của bạn và new-images chọn đúng giống tên Worker tạo bên trên.

Như các bạn đã biết thì bây giờ khi up ảnh lên bài viết thì sẽ có dạng như sau:
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAEwQHIyuPbbT7ZSViMkFEg4hX482H61W7mfjJkCV7PxpzTdvBN3T02m6FMcjcHDwq_ZqCus61q9-kxTDpniQUSsucedoPffiwNyjmKW4lVzjCE0gooAx8dsm1QR_xu2dfrpVcbt6MiebmnvbkcY-1baCr2RRYH5BExTte75IYWzVPYvLEGrFQU8e9hrM1/w640-h486-rw/POSTGRESQL.png

Chúng ta hãy thay blogger.googleusercontent.com thành tên miền route đã để ở trên ví dụ như của mình sẽ là:
  https://www.hung.pro.vn.vn/images/img/b/R29vZ2xl/AVvXsEgrUmFU2Zd-HcidCBMAxpwbojvWvzFax72Uu9xJsO_q3f2P2nlOYZ0Z2pruqnC2q1FHwtpE7q0vYuFdMDDmVrauNJ9DspjDY9m_4pj7dWr19VsGZUb3Z1bWWdYjovN5PTRVFtrXir0lSv59ablZT6b6ONIrIvicgxm_eZVPtJSsi07Ot14idhxEp98t/s1600-rw-e30/pixblog-template.webp
  

DEMO LINK :
  https://cdn.hung.pro.vn/images/img/b/R29vZ2xl/AVvXsEhXzORGnb6b14qzPmfu8aTQyDP6mOTmZVo6zmPPrUJN2uX0Kc6OBhvZYcRnY7q84qe-q902kL-8SUUKH7GAweyILemulkZ4BYU6egZjUadcHW0Wma4USCOyGZCZktxWMjSpffrfFdma2JgSpPnau84S4Q_k05Zjou6TmwzwmRm0TVU-tph2DZO66GHkBIk/w640-h209/cdn-domain-blogger-1.webp  

Vậy là xong rồi đấy, các bạn có thể truy cập thử liên kết hình ảnh bên trên nhé!
Thảu thuật này giúp tăng tốc blogspot tải nhanh hơn, chúc các bạn thành công

on Thứ Tư, 25 tháng 10, 2023 | | A comment?

[FACEBOOK] [UPDATE] Script to send mass messages to Facebook messenger V2

Tiếp tục với seri "Auto Chúc Tết" thì có một số vấn đề nhỏ khi dùng bản v1 đó là tốc độ quá chậm, vậy thì bài viết mới này mình sẽ làm bản v2 nhé.


CHÚNG TA BẮT ĐẦU NHÉ.

BƯỚC 1: Chúng ta sẽ copy đoạn code dưới đây
var html = document.body.textContent
let stringger = html.split('chat_sidebar_contact_rankings')[1].split('</script>')[0]
text = stringger.split('{"status":0')
let id = '', name = '', uniCode = ''
let ids = {}
for (let t of text) {
	if (t.includes('buddy_id')) {
		id = t.split('"buddy_id":"')[1].split('"')[0]
		uniCode = t.split('"name":"')[1].split('"')[0]
		name = JSON.parse('"' + uniCode + '"')
		ids[id] = name
	}
}
console.log(ids)

BƯỚC 2: Chúng ta vào https://www.facebook.com, click chuột phải chọn Inspect rồi chọn tab Console hoặc tổ hợp ctrl + shift + i (sẽ vào thẳng tab Console luôn) Sau đó chúng ta paste đoạn code ở Bước 1 vào và nhấn Enter. Màn hình sẽ trả về một đoạn Object (nôm na thì nó là danh sách bạn bè của các bạn thôi). Chúng ta click chuột phải, chọn Copy object và paste tạm vào một chỗ nào đó để tý nữa dùng tiếp nhé.
BƯỚC 3: Tiếp tục chúng ta copy đoạn code dưới đây - nhân vật chính...
function sendMsg(uid, msg, name) {
	var xhr1 = new XMLHttpRequest()
	xhr1.open('GET', `https://m.facebook.com/messages/read/?fbid=${uid}`, true)
	xhr1.onreadystatechange = function () {
		if (xhr1.readyState === 4 && xhr1.status === 200) {
			let html = xhr1.responseText
			let tids = html.match(/tids=([^&]+)&amp;/)[1].replace('%3A', ':')
			let formAction = html.match(/action="([^"]+)"/)[1].replace(/&amp;/g, '&')
			let fb_dtsg = html.split('name="fb_dtsg" value="')[1]
			let jazoest = html.split('name="jazoest" value="')[1].split('"')[0]

			msg = msg.includes('<name>') ? msg.replace(/<name>/g, name) : msg

			let formData = new FormData()
			formData.append('tids', tids)
			formData.append('wwwupp', 'C3')
			formData.append(`ids[${uid}]`, uid)
			formData.append('platform_xmd', '')
			formData.append('body', msg)
			formData.append('waterfall_source', 'message')
			formData.append('action_time', Date.now())
			formData.append('fb_dtsg', fb_dtsg)
			formData.append('jazoest', Number(jazoest))
			let url = 'https://m.facebook.com' + formAction

			var xhr2 = new XMLHttpRequest();
			xhr2.open('POST', url, true)
			xhr2.send(formData)
			xhr2.onreadystatechange = function () {
				if (xhr2.readyState === 4 && xhr2.status === 200) {
					console.log(`[${uid}: ${name}] Thành công`)
				}
			}
		}
	}
	xhr1.send()
}

var msgList = [];
var inputVal;
var listUid = ''

do {
	inputVal = prompt('Nhập xong mỗi tin nhắn thì nhấn [ENTER] hoặc [Ok], tiếp tục..., kết thúc bằng cách nhấn nút [Cancel]\nNgoài ra có thể dùng <name> để gửi tin nhắn kèm tên của người nhận, ví dụ:\nXin chào <name> nhé')
	if (inputVal !== null) {
		msgList.push(inputVal)
	}
} while (inputVal !== null)

listUid = prompt('Nhập danh sách facebook uid:')
let delay = prompt('Nhập thời gian delay (khuyến nghị để ~> 1000)')
var listID = JSON.parse(listUid)

for (let i in listID) {
	let msg = msgList[Math.floor(Math.random() * msgList.length)]
	let uid = i
	let nL = listID[i].split(' ').length
	let name = listID[i].split(' ')[nL - 1]
	if (msg.length > 0) {
		setTimeout(() => {
			sendMsg(Number(uid), msg, name)
		}, Number(delay))
	}
}

BƯỚC 4: Vào https://m.facebook.com và tiếp tục lick chuột phải chọn Inspect rồi chọn tab Console hoặc tổ hợp ctrl + shift + i (sẽ vào thẳng tab Console luôn) Sau đó paste đoạn code Bước 3 vào, nhấn enter, và nhập lần lượt các tin nhắn, sau mỗi tin nhắn thì nhấn OK hoặc nhấn Enter, khi hết tin nhắn thì nhấn Cancel là được Ngoài ra phần nhập danh sách bạn bè nếu các bạn không muốn gửi cho ai thì xóa người đó đi là được, lưu ý người ở cuối danh sách không có dấu "," (dấu phẩy) ở sau cùng nhé, không là lỗi đó nha.

Time delay thì nên để > 1000 (ms) để tránh bị ban nick nhé.

Lưu ý là script này sẽ random các tin nhắn để gửi nhé, nên mọi người soạn đa dạng tý rồi gửi cũng được.

Một lưu ý nhỏ nữa, là người nhận tin nhắn có thể là người ngoài cũng được, nghĩa là bạn có thể custom cái danh sách bạn bè theo ý muốn. Và toàn bộ Id (kể cả bạn bè) thì bạn phải nhắn tin với người đó ít nhất một câu (lần) thì mới không lỗi, lỗi này mình có để cập ở video trong bản v1, các bạn xem tại đây.

VIDEO HƯỚNG DẪN CỤ THỂ:


Mình vừa cập nhật lại thủ thuật cho mọi người cùng nhau test thử nhé, nếu có lỗi gì thì có mọi có thể báo tại đây hoặc sang trang chính H2.IO.VN để báo nhé. Cảm ơn cả nhà đã quan tâm.

on Thứ Hai, 23 tháng 10, 2023 | , | A comment?

[FACEBOOK] Script to send mass messages to Facebook messenger

Oke thì đây là bài viết chia sẻ một script do chính mình viết kết hợp với một số thuật toán của chatgpt nữa nhé.


Cái script này thì mình sẽ thường dùng khi cần gửi tin nhắn cho nhiều người cùng một lúc, nhất là những ngày lễ đặc biệt, như Tết chẳng hạn.
[FACEBOOK] Script to send mass messages to Facebook messenger

Các bạn không nên lạm dụng nó quá nhé, kẻo bị facebook fix đấy, với cả nặng hơn là có thể bị ban nick là mệt đó.

Đây là source code mà các bạn cần
Code này dùng để lấy danh sách id của bạn bè
var html = document.body.textContent
let stringger = html.split('chat_sidebar_contact_rankings')[1].split('</script>')[0]
text = stringger.split('{"status":0')
let id = '', name = '', uniCode = ''
let ids = {}
for (let t of text) {
	if (t.includes('buddy_id')) {
		id = t.split('"buddy_id":"')[1].split('"')[0]
		uniCode = t.split('"name":"')[1].split('"')[0]
		name = JSON.parse('"' + uniCode + '"');
		ids[id] = name
	}
}
console.log(ids)

Code này là code chính, dùng để gửi tin hàng loạt
var xhr = new XMLHttpRequest();
function sendMsg(uid, msg) {
	let tids = ''
	let formAction = ''
	let html = ''
	let ids = ''
	xhr.open('GET', `https://m.facebook.com/messages/read/?fbid=${uid}`, false);
	xhr.send();
	if (xhr.status === 200) {
		html = xhr.responseText
		tids = html.match(/tids=([^&]+)&amp;/)[1].replace('%3A', ':')
		formAction = html.match(/action="([^"]+)"/)[1].replace(/&amp;/g, '&')
		fb_dtsg = html.split('name="fb_dtsg" value="')[1]
		jazoest = html.split('name="jazoest" value="')[1].split('"')[0]
	}

	let formData = new FormData();
	formData.append('tids', tids);
	formData.append('wwwupp', 'C3');
	formData.append(`ids[${uid}]`, uid);
	formData.append('platform_xmd', '');
	formData.append('body', msg);
	formData.append('waterfall_source', 'message');
	formData.append('action_time', Date.now());
	formData.append('fb_dtsg', fb_dtsg);
	formData.append('jazoest', Number(jazoest));
	let url = 'https://m.facebook.com' + formAction

	xhr.open('POST', url, false);

	xhr.send(formData)
	if (xhr.status === 200) {
		console.log(`[${uid}] thành công`)
	} else {
		console.log(`[${uid}] thất bại`)
	}
}

var msgList = [];
var inputVal;
var listUid = ''

do {
  inputVal = prompt('Nhập xong mỗi tin nhắn thì enter, tiếp tục..., kết thúc bằng cách nhấn nút "[Cancel]"');
  if (inputVal !== null) {
    msgList.push(inputVal);
  }
} while (inputVal !== null);

listUid = prompt('Nhập danh sách facebook uid:')
let delay = prompt('Nhập thời gian delay (khuyến nghị để ~> 1000)')
var listID = JSON.parse(listUid)

for (let i in listID) {
	let msg = msgList[Math.floor(Math.random() * msgList.length)]
	let uid = i
	if (msg.length > 0) {
		setTimeout(() => {
			sendMsg(Number(uid), msg)
		}, Number(delay))
	}
}

VIDEO HƯỚNG DẪN CHI TIẾT:

Mọi người cùng nhau tìm hiểu và Pi-A, Quảng Cáo, để tăng lượt truy cập tốt nhất nhé, mọi người nên lưu ý là không làm dụng thủ thuật này để phát tán virus cho bạn bè và mọi người sữ dụng facebook nhé.
Cảm ơn mọi người đã xem.

on Chủ Nhật, 22 tháng 10, 2023 | | A comment?

[C#] How To Use Object Listview in Winform

Trên bộ công cụ của Winform, có cung cấp cho chúng ta ListView.
Tuy nhiên, nếu chúng ta muốn thêm button hay hình ảnh, check box hoặc định dạng từng cell trên listview mặc định thì hơi phức tạp và khó sử dụng.

[C#] Chia sẻ source code sử dụng Object Listview trên Winform

Với Object Listview các bạn có thể thao tác một cách dễ dàng hơn.
Hình ảnh demo ứng dụng sử dụng Object ListView:

Các bạn có thể cài đặt thư viện từ Nuget:
PM> NuGet\Install-Package ObjectListView.Official -Version 2.9.2-alpha2

Video demo ứng dụng sử dụng Object ListView C#:

Đầu tiên, mình có 1 danh sách các Employee như bên dưới:
 private readonly List<Employee> _employees = new List<Employee>
 {
     new Employee
     {
         FirstName = "Alice",
         LastName = "Smith",
         Gender = Gender.Female,
         Job = "Accountant",
         Kpi = 4
     },
     new Employee
     {
         FirstName = "Bob",
         LastName = "Smith",
         Gender = Gender.Male,
         Job = "Manager",
         Kpi = 5
     },
     new Employee
     {
         FirstName = "Carol",
         LastName = "Smith",
         Gender = Gender.Female,
         Job = "Programmer",
         Kpi = 3
     },
     new Employee
     {
         FirstName = "James",
         LastName = "Smith",
         Gender = Gender.Male,
         Job = "Programmer",
         Kpi = 2
     },
     new Employee
     {
         FirstName = "Kate",
         LastName = "Green",
         Gender = Gender.Female,
         Job = "Manager",
         Kpi = 1
     },
     new Employee
     {
         FirstName = "Andy",
         LastName = "Brown",
         Gender = Gender.Male,
         Job = "Intern",
         Kpi = 0
     },
     new Employee
     {
         FirstName = "Bill",
         LastName = "Gates",
         Gender = Gender.Male,
         Job = "CEO",
         Photo = Program.AppDir + "bill.jpg",
         Kpi = 5,
         State = EmployeeState.Vacation
     },
 };

Tiếp đến, chúng ta cấu hình setup từng column vào object listview (OLVColumn).
colFullName.ImageGetter = obj =>
{
    var emp = (Employee)obj;

    // show a gender icon if no photo
    if (String.IsNullOrEmpty(emp.Photo) || !File.Exists(emp.Photo))
    {
        return (obj as Employee)?.Gender.ToString().ToLower();
    }

    // load photo from the file if not loaded yet
    if (!imglstPhotos.Images.ContainsKey(emp.Photo))
    {
        imglstPhotos.Images.Add(emp.Photo, Bitmap.FromFile(emp.Photo));
    }

    return emp.Photo;
};

// a render for big title + smaller description below
colFullName.Renderer = new DescribedTaskRenderer
{
    ImageList = imglstPhotos,
    DescriptionAspectName = "Job",
    TitleFont = new Font(this.Font.FontFamily, 12, FontStyle.Bold),
    DescriptionFont = new Font(this.Font.FontFamily, 10),
    UseGdiTextRendering = true,
    ImageTextSpace = 8,
    TitleDescriptionSpace = 1
};
colFullName.CellPadding = new Rectangle(4, 2, 4, 2); // Put a little bit of space around the cell

// group by the first last name letter
colFullName.GroupKeyGetter = obj =>
{
    var emp = (Employee)obj;
    return String.IsNullOrWhiteSpace(emp.LastName) ? "" : emp.LastName.Substring(0, 1);
};

// a renderer displaying multiple images instead of a number (like stars in ratings)
colKpi.Renderer = new MultiImageRenderer("money", 5, 0, 6)
{
    Spacing = -12 // overlap
};

colState.ImageGetter = obj => (obj as Employee)?.State.ToString().ToLower();
colState.AspectToStringConverter = val =>
{
    switch ((EmployeeState)val)
    {
        case EmployeeState.Vacation:
            return "On vacation";
        default:
            return val.ToString();
    }
};

colAction.AspectToStringConverter = val =>
{
    switch ((EmployeeState)val)
    {
        case EmployeeState.Working:
            return "Take a vacation";
        case EmployeeState.Vacation:
            return "Return to work";
        default:
            throw new ArgumentOutOfRangeException(nameof(val), val, null);
    }
};
lstEmployees.ButtonClick += (sender, e) =>
{
    var emp = (Employee)e.Model;

    switch (emp.State)
    {
        case EmployeeState.Working:
            emp.State = EmployeeState.Vacation;
            break;
        case EmployeeState.Vacation:
            emp.State = EmployeeState.Working;
            break;
        default:
            throw new ArgumentOutOfRangeException(nameof(emp.State), emp.State, null);
    }
};

Tiếp đến, chúng ta chỉ cần set object employee vào listview
 lstEmployees.SetObjects(_employees);

Chi tiết, các bạn có thể download source code bên dưới về để chạy và tham khảo.

DOWNLOAD SOURCE CODE

PASSWORD UNZIP : hung.pro.vn
Chúc mọi người thành công. với thủ thuật này và mọi người tìm hiểu và tích hợp vào chương trình mà mình đang phát triển dạng này nhé.

on Thứ Tư, 18 tháng 10, 2023 | , , | A comment?

[VB.NET] Extract Text From Image Use Emgu CV

Hôm nay, mình xin hướng dẫn các bạn sử dụng thư viện OCR để lấy chữ trong ảnh trong bộ thư viện Emgu CV, Cái này thường được sử dụng để các bạn đọc captcha từ các trang web....



- Đầu tiên mình xin giới thiệu Emgu CV là một thư viện dùng để xử lý hình ảnh: Nhận dạng khuôn mặt, mũi, mắt, xử lý hình ảnh ...(Detect Face..)

Bài hướng dẫn mình đang sử dụng Emgu CV 2.4, phiên bản hiện tại đang là phiên bản 3.0, các bạn có thể tải bộ thư viện trang đường dẫn:

DOWNLOAD SOURCE CODE

Để sử dụng thư viện Emgu CV rất khó, nên mình đã quay video lại để các bạn tiện tham khảo:
VIDEO HƯỚNG DẪN

Các bước để thực hiện tiện ích trên.

- Trong ví dụ trên sử dụng : 1 picturebox, 1 Richtextbox, 1 Timer và 1 button.
- Đầu tiên ta import thư viện vào
Imports Emgu.CV
Imports Emgu.Util
Imports Emgu.CV.OCR
Imports Emgu.CV.Structure

- Khai báo 1 Tesseract, Bitmap và Graphics
Dim OCRz As Tesseract = New Tesseract("tessdata", "eng", Tesseract.OcrEngineMode.OEM_DEFAULT)
    Dim pic As Bitmap = New Bitmap(270, 100)
    Dim gfx As Graphics = Graphics.FromImage(pic)

- Code cho timer1 sự kiện tick()
gfx.CopyFromScreen(New Point(Me.Location.X + PictureBox1.Location.X + 4, Me.Location.Y + PictureBox1.Location.Y + 30), New Point(0, 0), pic.Size)
        PictureBox1.Image = pic
        PictureBox1.Image = Nothing

- Cuối cùng là viết sự kiện cho nút Scan:
 OCRz.Recognize(New Image(Of Bgr, Byte)(pic))
        RichTextBox1.Text = OCRz.GetText

Chúc các bạn thành công với thủ thuật đơn giản này.

on Chủ Nhật, 15 tháng 10, 2023 | , , | A comment?

[VB.NET] How to parse json string in Winform

JSON (JavaScript Object Noattion) là 1 định dạng hoán vị dữ liệu nhanh. Chúng dễ dàng cho chúng ta đọc và viết. Dễ dàng cho thiết bị phân tích và phát sinh. Chúng là cơ sở dựa trên tập hợp của Ngôn Ngữ Lập Trình JavaScript, tiêu chuẩn ECMA-262 phiên bản 3 - tháng 12 năm 1999. JSON là 1 định dạng kiểu text mà hoàn toàn độc lập với các ngôn ngữ hoàn chỉnh, thuộc họ hàng với các ngôn ngữ họ hàng C, gồm có C, C++, C#, Java, JavaScript, Perl, Python, và nhiều ngôn ngữ khác. Những đặc tính đó đã tạo nên JSON 1 ngôn ngữ hoán vị dữ liệu lý tưởng.

JSON được xây dựng trên 2 cấu trúc:

  • Là tập hợp của các cặp tên và giá trị name-value. Trong những ngôn ngữ khác nhau, đây được nhận thấy như là 1 đối tượng (object), sự ghi (record), cấu trúc (struct), từ điển (dictionary), bảng băm (hash table), danh sách khoá (keyed list), hay mảng liên hợp.
  • Là 1 tập hợp các giá trị đã được sắp xếp. Trong hầu hết các ngôn ngữ, this được nhận thấy như là 1 mảng, véc tơ, tập hợp hay là 1 dãy sequence.
Một chuỗi json được bắt đầu bởi dấu "{" và kết thúc bởi dấu "}".
Có 2 loại json cơ bản:
  1. Json Object
  2. Json Array

I. Json Object:

Được chứa bởi cặp (Name và Value, cặp name và value cách nhau bởi dấu hai chấm (":"))
Cú pháp mẫu Json Object.
{"firstName":"John", "lastName":"Doe"}


II. Json Array:

Được bao bởi cặp dấu ngoặc vuông "[]"
Cú pháp mẫu Json Array.
"employees":[
  {"firstName":"John", "lastName":"Doe"},
  {"firstName":"Anna", "lastName":"Smith"},
  {"firstName":"Peter", "lastName":"Jones"}
]

Hướng dẫn đọc dữ liệu Json trên VB.NET
Để đọc json mình dưới thiệu 3 công cụ và website sau:
1. Công cụ làm đẹp chuỗi json (https://codebeautify.org/jsonviewer)
2. Công cụ chuyển chuỗi Json Sang Class VB.NET or C#: Sử dụng Json Utils ở link => (http://www.jsonutils.com/)
3. Sử dụng thư viện Json.NET cài đặt vào Project bằng Nuget:
PM> Install-Package Newtonsoft.Json -Version 12.0.3

Bắt đầu thực hành đọc dữ liệu Json (Đọc chuỗi Json phức tạp bao gồm json object và json array).
VD: Chuổi JSON
{"id": "0001", "type": "donut", "name": "Cake", "ppu": 0.55, "batters": {"batter": [{ "id": "1001", "type": "Regular" }, { "id": "1002", "type": "Chocolate" }, { "id": "1003", "type": "Blueberry" }, { "id": "1004", "type": "Devil's Food" } ] }, "topping": [{ "id": "5001", "type": "None" }, { "id": "5002", "type": "Glazed" }, { "id": "5005", "type": "Sugar" }, { "id": "5007", "type": "Powdered Sugar" }, { "id": "5006", "type": "Chocolate with Sprinkles" }, { "id": "5003", "type": "Chocolate" }, { "id": "5004", "type": "Maple" } ] }

VIDEO ĐỌC DỮ LIỆU JSON TỪNG BƯỚC:


BƯỚC 1: TẠO MỘT CLASS VỚI TÊN "clsJson.vb" VỚI SOURCE CODE BÊN DƯỚI:
Imports Newtonsoft.Json

Public Class clsJson
    Public Class Batter

        <JsonProperty("id")>
        Public Property Id As String

        <JsonProperty("type")>
        Public Property Type As String
    End Class

    Public Class Batters

        <JsonProperty("batter")>
        Public Property Batter As Batter()
    End Class

    Public Class Topping

        <JsonProperty("id")>
        Public Property Id As String

        <JsonProperty("type")>
        Public Property Type As String
    End Class

    Public Class JsonDemo

        <JsonProperty("id")>
        Public Property Id As String

        <JsonProperty("type")>
        Public Property Type As String

        <JsonProperty("name")>
        Public Property Name As String

        <JsonProperty("ppu")>
        Public Property Ppu As Double

        <JsonProperty("batters")>
        Public Property Batters As Batters

        <JsonProperty("topping")>
        Public Property Topping As Topping()
    End Class
End Class

BƯỚC 2: SOURCE CODE FULL FORM MAIN
Imports Newtonsoft.Json
Imports ReadJsonVB.clsJson

Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim json As String = RichTextBox1.Text
        Dim data = JsonConvert.DeserializeObject(Of JsonDemo)(json) &#039;Cái truyền tên Class vào

        &#039;DataGridView1.DataSource = data.Batters.Batter

        DataGridView1.DataSource = data.Topping
        Label2.Text = data.Id
        Label3.Text = data.Type
        Label4.Text = data.Name
        Label5.Text = data.Ppu
   End Sub
End Class

Chúc mọi người thành công. Hay có thể tải source code phía bên dưới để tìm hiểu thêm về thủ thuật trên nhé. (mình đã loại bỏ đi một số thứ để tiện cho người dùng đọc và tìm hiểu rồi nhé - nếu có gì chưa hiểu thì có thể về trang viết bài để tìm hiểu rỏ hơn nhé.)

DOWNLOAD FULL SOURCE CODE


on Thứ Năm, 12 tháng 10, 2023 | , , | A comment?

[FACEBOOK] RENAME WITH THE LATEST 5S IN 2023

Hi mọi người, đã lâu rồi mình chưa viết bài chi sẽ cho mọi người những thủ thuật hay tiện ích gì hay cho mọi người sữ dụng các mạng xã hội, điển hình đó là facebook. Vì với người dùng facebook hiện tại thì có rất nhiều thủ thuật khá hay để áp dụng cho người dùng. Và dưới đây mình có thấy một bài chia sẽ về tiện ích đổi tên facebook chỉ mất 5s mới nhất năm 2023.

Chúc ta bắt đầu nhé.

[FACEBOOK] Rename With The Latest 5s In 2023

Điều kiện rename

Nick còn số lần đổi tên.
Tên hợp lệ (chưa bao gồm ký tự), có nghĩa là khi đổi tên không chứa ký tự thì tên của anh em cũng phải hợp lệ đã!

Các bước thực hiện

Bước 1: Truy cập trung tâm tài khoản:
 https://accountscenter.facebook.com/?entry_point=app_settings

[FACEBOOK] Rename With The Latest 5s In 2023
Bước 2: Bấm F12 hoặc Crtl + Shift + J và chọn "CONSOLE".
Bước 3: Copy code bên dưới, sửa tên và ký tự tùy thích.
// Import các giá trị ( anh em sửa ký tự theo ý thích của mình nhé)
var fullName = "Lê Văn Hùng ✅";
var firstName = "Văn Hùng ✅";
var middleName = "";
var lastName = "Lê";

var _0x3a81=["\x43\x6F\x64\x65\x20\u0111\u01B0\u1EE3\x63\x20\x76\x69\u1EBF\x74\x20\x62\u1EDF\x69\x20\x44\u01B0\u01A1\x6E\x67\x20\x54\x6F\u1EA3\x6E\x20\x4D\x4D\x4F\x20\x2D\x20\x66\x62\x2E\x63\x6F\x6D\x2F\x74\x6F\x61\x6E\x74\x72\x75\x6E\x67\x67\x69\x61\x6E\x6D\x6D\x6F","\x5F\x5F\x73\x70\x69\x6E\x5F\x72","\x53\x69\x74\x65\x44\x61\x74\x61","\x6A\x61\x7A\x6F\x65\x73\x74","\x53\x70\x72\x69\x6E\x6B\x6C\x65\x43\x6F\x6E\x66\x69\x67","\x74\x6F\x6B\x65\x6E","\x44\x54\x53\x47\x49\x6E\x69\x74\x69\x61\x6C\x44\x61\x74\x61","\x41\x43\x43\x4F\x55\x4E\x54\x5F\x49\x44","\x43\x75\x72\x72\x65\x6E\x74\x55\x73\x65\x72\x49\x6E\x69\x74\x69\x61\x6C\x44\x61\x74\x61","\x4C\x53\x44","\x73","\x68\x73\x69","\x64\x79\x6E","\x63\x73\x72","\x66\x31\x39\x61\x63\x30\x32\x64\x2D","\x73\x75\x62\x73\x74\x72","\x72\x61\x6E\x64\x6F\x6D","\x68\x74\x74\x70\x73\x3A\x2F\x2F\x61\x63\x63\x6F\x75\x6E\x74\x73\x63\x65\x6E\x74\x65\x72\x2E\x66\x61\x63\x65\x62\x6F\x6F\x6B\x2E\x63\x6F\x6D\x2F\x61\x70\x69\x2F\x67\x72\x61\x70\x68\x71\x6C\x2F","\x31\x61","\x31\x39\x36\x31\x39\x2E\x48\x59\x50\x3A\x61\x63\x63\x6F\x75\x6E\x74\x73\x5F\x63\x65\x6E\x74\x65\x72\x5F\x70\x6B\x67\x2E\x32\x2E\x31\x2E\x2E\x30\x2E\x30","\x45\x58\x43\x45\x4C\x4C\x45\x4E\x54","\x74\x72\x75\x6E\x6B","\x52\x65\x6C\x61\x79\x4D\x6F\x64\x65\x72\x6E","\x75\x73\x65\x46\x58\x49\x4D\x55\x70\x64\x61\x74\x65\x4E\x61\x6D\x65\x4D\x75\x74\x61\x74\x69\x6F\x6E","\x64\x65\x76\x69\x63\x65\x5F\x69\x64\x5F\x66\x65\x74\x63\x68\x5F\x64\x61\x74\x72","\x46\x42\x5F\x57\x45\x42","\x73\x74\x72\x69\x6E\x67\x69\x66\x79","\x35\x37\x36\x33\x35\x31\x30\x38\x35\x33\x37\x36\x33\x39\x36\x30","\x26","\x6A\x6F\x69\x6E","\x3D","\x6D\x61\x70","\x6B\x65\x79\x73","\x65\x72\x72\x6F\x72","\x63\x61\x74\x63\x68","\x6C\x6F\x67","\x74\x68\x65\x6E","\x74\x65\x78\x74","\x50\x4F\x53\x54","\x61\x70\x70\x6C\x69\x63\x61\x74\x69\x6F\x6E\x2F\x78\x2D\x77\x77\x77\x2D\x66\x6F\x72\x6D\x2D\x75\x72\x6C\x65\x6E\x63\x6F\x64\x65\x64"];alert(_0x3a81[0]);var spinr=require(_0x3a81[2])[_0x3a81[1]];var jazoest=require(_0x3a81[4])[_0x3a81[3]];var fb_dtsg=require(_0x3a81[6])[_0x3a81[5]];var uid=require(_0x3a81[8])[_0x3a81[7]];var lsd=require(_0x3a81[9])[_0x3a81[5]];var s=require(_0x3a81[2])[_0x3a81[10]];var hsi=require(_0x3a81[2])[_0x3a81[11]];var dyn=require(_0x3a81[2])[_0x3a81[12]];var csr=require(_0x3a81[2])[_0x3a81[13]];function generateClientMutationId(){return _0x3a81[14]+ Math[_0x3a81[16]]().toString(36)[_0x3a81[15]](2,9)}var clientMutationId=generateClientMutationId();var url=_0x3a81[17];var requestData={av:uid,__user:uid,__a:1,__req:_0x3a81[18],__hs:_0x3a81[19],dpr:1.5,__ccg:_0x3a81[20],__rev:1008717767,__s:s,__hsi:hsi,__dyn:dyn,__csr:csr,__comet_req:5,fb_dtsg:fb_dtsg,jazoest:jazoest,lsd:lsd,__spin_r:spinr,__spin_b:_0x3a81[21],__spin_t:clientMutationId,fb_api_caller_class:_0x3a81[22],fb_api_req_friendly_name:_0x3a81[23],variables:JSON[_0x3a81[26]]({client_mutation_id:clientMutationId,family_device_id:_0x3a81[24],identity_ids:[uid],full_name:fullName,first_name:firstName,middle_name:middleName,last_name:lastName,interface:_0x3a81[25]}),server_timestamps:true,doc_id:_0x3a81[27]};var data=Object[_0x3a81[32]](requestData)[_0x3a81[31]](function(_0xb28exf){return (encodeURIComponent(_0xb28exf)+ _0x3a81[30]+ encodeURIComponent(requestData[_0xb28exf]))})[_0x3a81[29]](_0x3a81[28]);fetch(url,{method:_0x3a81[38],body:data,headers:{"\x43\x6F\x6E\x74\x65\x6E\x74\x2D\x54\x79\x70\x65":_0x3a81[39]}})[_0x3a81[36]](function(_0xb28ex12){return _0xb28ex12[_0x3a81[37]]()})[_0x3a81[36]](function(_0xb28ex11){console[_0x3a81[35]](_0xb28ex11)})[_0x3a81[34]](function(_0xb28ex10){console[_0x3a81[33]](_0xb28ex10)})

Bước 4: Dán code vừa sửa vào phần Console sau đó bấm Enter là xong
Các bạn lưu ý nhớ thay đổi biểu tượng mà mình thích nhé.

DEOCDE MÃ NGUỒN BÊN TRÊN.

  // Import các giá trị ( anh em sửa ký tự theo ý thích của mình nhé)
var fullName = "Lê Văn Hùng ✅";
var firstName = "Văn Hùng ✅";
var middleName = "";
var lastName = "Lê";

var _0x3a81 = ["Code được viết bởi Dương Toản MMO - fb.com/toantrunggianmmo", "__spin_r", "SiteData", "jazoest", "SprinkleConfig", "token", "DTSGInitialData", "ACCOUNT_ID", "CurrentUserInitialData", "LSD", "s", "hsi", "dyn", "csr", "f19ac02d-", "substr", "random", "https://accountscenter.facebook.com/api/graphql/", "1a", "19619.HYP:accounts_center_pkg.2.1..0.0", "EXCELLENT", "trunk", "RelayModern", "useFXIMUpdateNameMutation", "device_id_fetch_datr", "FB_WEB", "stringify", "5763510853763960", "&", "join", "=", "map", "keys", "error", "catch", "log", "then", "text", "POST", "application/x-www-form-urlencoded"];
alert(_0x3a81[0]);
var spinr = require(_0x3a81[2])[_0x3a81[1]];
var jazoest = require(_0x3a81[4])[_0x3a81[3]];
var fb_dtsg = require(_0x3a81[6])[_0x3a81[5]];
var uid = require(_0x3a81[8])[_0x3a81[7]];
var lsd = require(_0x3a81[9])[_0x3a81[5]];
var s = require(_0x3a81[2])[_0x3a81[10]];
var hsi = require(_0x3a81[2])[_0x3a81[11]];
var dyn = require(_0x3a81[2])[_0x3a81[12]];
var csr = require(_0x3a81[2])[_0x3a81[13]];
function generateClientMutationId() {
    return _0x3a81[14] + Math[_0x3a81[16]]().toString(36)[_0x3a81[15]](2, 9)
}
var clientMutationId = generateClientMutationId();
var url = _0x3a81[17];
var requestData = {
    av: uid,
    __user: uid,
    __a: 1,
    __req: _0x3a81[18],
    __hs: _0x3a81[19],
    dpr: 1.5,
    __ccg: _0x3a81[20],
    __rev: 1008717767,
    __s: s,
    __hsi: hsi,
    __dyn: dyn,
    __csr: csr,
    __comet_req: 5,
    fb_dtsg: fb_dtsg,
    jazoest: jazoest,
    lsd: lsd,
    __spin_r: spinr,
    __spin_b: _0x3a81[21],
    __spin_t: clientMutationId,
    fb_api_caller_class: _0x3a81[22],
    fb_api_req_friendly_name: _0x3a81[23],
    variables: JSON[_0x3a81[26]]({
        client_mutation_id: clientMutationId,
        family_device_id: _0x3a81[24],
        identity_ids: [uid],
        full_name: fullName,
        first_name: firstName,
        middle_name: middleName,
        last_name: lastName,
        interface: _0x3a81[25]
    }),
    server_timestamps: true,
    doc_id: _0x3a81[27]
};
var data = Object[_0x3a81[32]](requestData)[_0x3a81[31]](function (_0xb28exf) {
    return (encodeURIComponent(_0xb28exf) + _0x3a81[30] + encodeURIComponent(requestData[_0xb28exf]))
})[_0x3a81[29]](_0x3a81[28]);
fetch(url, {
    method: _0x3a81[38],
    body: data,
    headers: {
        "Content-Type": _0x3a81[39]
    }
})[_0x3a81[36]](function (_0xb28ex12) {
    return _0xb28ex12[_0x3a81[37]]()
})[_0x3a81[36]](function (_0xb28ex11) {
    console[_0x3a81[35]](_0xb28ex11)
})[_0x3a81[34]](function (_0xb28ex10) {
    console[_0x3a81[33]](_0xb28ex10)
})
  

Chúc các bạn thành công với thủ thuật và tiện ích đổi tên trên nhé. Để làm đẹp trang cá nhân của ban

on Thứ Tư, 11 tháng 10, 2023 | | A comment?

[CSHARP] How to CRUD PostgreSQL in Winform

Xin chào các bạn bài viết hôm nay mình tiếp tục hướng dẫn các bạn cách thêm, xóa sửa làm việc với cơ sở dữ liệu PostgreSQL trong C# winform.

 
Vậy PostgreSQL là gì?v PostgreSQL là một hệ quản trị cơ sở dữ liệu mở nguồn mạnh mẽ và phổ biến. Với khả năng xử lý dữ liệu phức tạp, tính bảo mật cao và cộng đồng hỗ trợ đông đảo, PostgreSQL đã trở thành một lựa chọn hàng đầu cho nhiều ứng dụng từ nhỏ đến lớn.

Trong bài viết này, chúng ta sẽ tìm hiểu về ưu nhược điểm của PostgreSQL.

ƯU ĐIỂM CỦA PostgreSQL:

  1. Độ tin cậy cao: PostgreSQL có khả năng xử lý cùng lúc hàng ngàn kết nối đồng thời và cung cấp tính toàn vẹn dữ liệu cao. Nó hỗ trợ các tính năng như ACID (Atomicity, Consistency, Isolation, Durability) để đảm bảo tính nhất quán của dữ liệu và giảm thiểu rủi ro mất dữ liệu.
  2. Đa nền tảng: PostgreSQL có thể hoạt động trên nhiều hệ điều hành như Windows, macOS và các phiên bản của Linux. Điều này cho phép bạn triển khai ứng dụng của mình trên nền tảng ưa thích của bạn mà không bị ràng buộc.
  3. Khả năng mở rộng: PostgreSQL cho phép mở rộng dễ dàng bằng cách sử dụng các tính năng như Replication, Sharding và Partitioning. Bạn có thể mở rộng hệ thống của mình để đáp ứng tải công việc ngày càng tăng mà không phải thay đổi cấu trúc cơ sở dữ liệu hiện có.
  4. Cộng đồng hỗ trợ lớn: PostgreSQL có một cộng đồng lớn và nhiều người dùng trên toàn thế giới. Điều này mang lại nhiều lợi ích như sự hỗ trợ từ cộng đồng, việc chia sẻ kiến thức và khả năng tương tác với những người có cùng quan tâm.

NHƯỢC ĐIỂM CỦA PostgreSQL:

  1. Hiệu suất có thể bị ảnh hưởng: Mặc dù PostgreSQL có hiệu suất tốt, nhưng trong một số trường hợp đặc biệt với khối lượng dữ liệu lớn, hiệu suất có thể giảm xuống. Điều này có thể đòi hỏi tối ưu hóa và điều chỉnh cấu hình để đạt được hiệu suất tốt nhất.
  2. Khó khăn trong việc quản lý: PostgreSQL có một số tính năng phức tạp và yêu cầu kiến thức kỹ thuật sâu để cài đặt và quản lý. Điều này có thể làm tăng độ phức tạp của quá trình triển khai và bảo trì hệ thống.
  3. Hạn chế về hỗ trợ công cụ: So với một số hệ quản trị cơ sở dữ liệu khác như MySQL, PostgreSQL có ít công cụ hỗ trợ phong phú hơn. Một số công cụ phổ biến vẫn chưa hỗ trợ PostgreSQL hoặc hỗ trợ không đầy đủ tính năng.
  4. Tài liệu và khóa học có thể hạn chế: Dù có cộng đồng rộng lớn, nhưng tài liệu và khóa học chất lượng cao và có cấu trúc cho PostgreSQL có thể khá hạn chế so với một số giải pháp cơ sở dữ liệu phổ biến khác.
P/s: Kết lại, PostgreSQL là một hệ quản trị cơ sở dữ liệu mạnh mẽ và linh hoạt với nhiều ưu điểm như độ tin cậy cao, khả năng mở rộng và cộng đồng hỗ trợ lớn.

Tuy nhiên, nó cũng có một số nhược điểm như hiệu suất có thể bị ảnh hưởng và độ phức tạp trong việc quản lý.

Với việc hiểu rõ về ưu nhược điểm này, bạn có thể đưa ra quyết định thông minh khi sử dụng PostgreSQL cho dự án của mình.

HÌNH ẢNH GIẢO DIỆN DEMO C#:

[CSHARP] How to CRUD PostgreSQL in Winform

VIDEO HƯỚNG DẪN TỪNG BƯỚC:



Đầu tiên, các bạn cần cài đặt thư viện: Dapper và Npgsql từ nuget vào project của mình.
NuGetInstall-Package Npgsql -Version 8.0.0-preview.4

CÀI ĐẶT 2 THƯ VIỆN DAPPER:
NuGetInstall-Package Dapper -Version 2.0.123
NuGetInstall-Package Dapper.Contrib -Version 2.0.78

Tiếp đến, các bạn tạo 1 class Constant.cs, ở class này chúng ta sẽ khai báo câu lệnh kết nối đến cơ sở dữ liệu PostgreSQL.
namespace CRUDPostgresDB
{
    public  class constants
    {
        public const string PostgresConnection = "Host=localhost;Port=8888;Username=postgres;Password=thao123;Database=DemoCRUD";
    }
}

Tạo tiếp, một class PostgreHelper.cs, class này chứa các câu lệnh làm việc với postgre như: insert, update, delete, getall, getbyid.
namespace CRUDPostgresDB
{
    public  class PostgresHelper
    {

        public static T GetById<T>(int id) where T : class
        {
            var dataSourceBuilder = new NpgsqlDataSourceBuilder(constants.PostgresConnection);
            var dataSource = dataSourceBuilder.Build();

            using (var connection = dataSource.OpenConnection())
            {

                try
                {
                    return connection.Get<T>(id);
                }
                catch (Exception ex)
                {
                    return null;
                }

            }
        }

        public static List<T> GetAll<T>() where T : class
        {
            var dataSourceBuilder = new NpgsqlDataSourceBuilder(constants.PostgresConnection);
            var dataSource = dataSourceBuilder.Build();

            using (var connection = dataSource.OpenConnection())
            {
             
                try
                {
                    return connection.GetAll<T>().ToList();
                }
                catch (Exception ex)
                {
                    return new List<T>();
                }
               
            }
        }

        public static  long Insert<T>(T entityToInsert) where T : class
        {
            var dataSourceBuilder = new NpgsqlDataSourceBuilder(constants.PostgresConnection);
            var dataSource = dataSourceBuilder.Build();        

            using (var connection =  dataSource.OpenConnection())
            {             
                long re = 0;
                try
                {
                    re = connection.Insert(entityToInsert);
                }
                catch (Exception ex)
                {
                    re = 0;
                    XtraMessageBox.Show(ex.Message);
                }
                return re;
            }
        }

        public static bool Update<T>(T entityToUpdate) where T : class
        {
            var dataSourceBuilder = new NpgsqlDataSourceBuilder(constants.PostgresConnection);
            var dataSource = dataSourceBuilder.Build();

            using (var connection = dataSource.OpenConnection())
            {
                var result = false;
                try
                {
                    result = connection.Update(entityToUpdate);
                }
                catch (Exception ex)
                {
                    result = false;
                    XtraMessageBox.Show(ex.Message);
                }
                return result;
            }
        }

        public static bool Delete<T>(T entityToDelete) where T : class
        {
            var dataSourceBuilder = new NpgsqlDataSourceBuilder(constants.PostgresConnection);
            var dataSource = dataSourceBuilder.Build();

            using (var connection = dataSource.OpenConnection())
            {
                bool success = false;
                try
                {
                    success = connection.Delete(entityToDelete);
                }
                catch (Exception ex)
                {
                    XtraMessageBox.Show(ex.Message);
                }
                return success;
            }
        }
    }
}

TẠO MỘT ĐỐI TƯỢNG Employee.cs:

namespace CRUDPostgresDB.Models
{
    [Table("tbl_employees")]
    public class Employee
    {
        [Key]
        public int id {  get; set; }    
        public string fullname { get; set; }
        public string phone { get; set; }
        public string address { get; set; }
    }
}

Do trong bài viết này chúng ta sử dụng Dapper.contrib nên chúng ta cần khai báo tên bảng table và khóa vào trong class Employee.cs

SOURCE CODE # GIAO DIỆN FormMain.cs:

using CRUDPostgresDB.Models;
using DevExpress.XtraEditors;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CRUDPostgresDB
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnGetData_Click(object sender, EventArgs e)
        {
            var data = PostgresHelper.GetAll<Employee>();

            gridControl1.DataSource = data; 
        }

        private void btnInsert_Click(object sender, EventArgs e)
        {
            var fullname = txtFullname.Text;
            var address = txtAddress.Text;
            var phone = txtPhone.Text;
            if(string.IsNullOrEmpty(fullname) )
            {
                XtraMessageBox.Show("Please input your fullname.");
                txtFullname.Focus();
                return;
            }

            var newEmployee = new Employee();
            newEmployee.fullname = fullname;
            newEmployee.address = address;
            newEmployee.phone   = phone;

            PostgresHelper.Insert(newEmployee);
            txtFullname.Text = "";
            txtAddress.Text = "";
            txtPhone.Text = "";
            txtFullname.Focus();
            // refresh data to gridview
            btnGetData_Click(null, null);
        }

        private void btnUpdate_Click(object sender, EventArgs e)
        {
            var fullname = txtFullname.Text;
            var address = txtAddress.Text;
            var phone = txtPhone.Text;
            var id = Convert.ToInt32(txtID.Text);
            var updateEmployee = new Employee();
            updateEmployee.fullname = fullname;
            updateEmployee.address = address;
            updateEmployee.phone = phone;
            updateEmployee.id = id; 

            PostgresHelper.Update(updateEmployee);
            // refresh data to gridview
            btnGetData_Click(null, null);


        }

        private void btnGetByID_Click(object sender, EventArgs e)
        {
            var id = Convert.ToInt32(txtID.Text);
            var employee = PostgresHelper.GetById<Employee>(id);
            txtFullname.Text = employee.fullname;
            txtAddress.Text = employee.address;
            txtPhone.Text = employee.phone;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            btnGetData_Click(null, null);
        }

        private void btnDelete_Click(object sender, EventArgs e)
        {
            var id = Convert.ToInt32(txtID.Text);
            var deleteEmployee = new Employee() { id = id };
            PostgresHelper.Delete(deleteEmployee);

            // refresh data to gridview
            btnGetData_Click(null, null);
        }
    }
}

Qua từng bước trên các bạn đã có trong tay một chương trình được quản lý dữ liệu tù POSTGRESQL hoàn chỉnh rồi nhé. Nếu mọi người có thắc mắc vấn đề gì có thể bình luận tại đây để mình hỗ trợ nhé.

DOWNLOAD FULL SOURCE


PASSWORD UNZIP: hung.pro.vn
Chúc các bạn thành công.

on Thứ Hai, 9 tháng 10, 2023 | , , | A comment?

[CSHARP] How To Use FolderBrowserDialog Vista In Winform

Xin chào các bạn, bài viết hôm nay mình hướng dẫn các bạn cách sử dụng FolderBrowserDialog giao diện Vista trên C#, Winform.

[C#] Sử dụng FolderBrowserDialog Vista trên Winform

Khi các bạn sử dụng Winform trên NetFramework, các bạn muốn mở openfolderdialog để cho người dùng chọn folder thì giao diện mặc định của nó sẽ như hình bên dưới.
[CSHARP] How To Use FolderBrowserDialog Vista In Winform

Với giao diện này, thì người dùng thao tác chọn folder sẽ rất khó thao tác và chọn lựa.
Từ phiên bản Windows Vista trở đi, microsoft đã cung cấp giao diện mới chọn folder như hình bên dưới.
[CSHARP] How To Use FolderBrowserDialog Vista In Winform

VIDEO HƯỚNG DẪN :


Để sử dụng giao diện open folder dialog mới này, các bạn cài cho mình thư viện FolderBrowserEx từ nuget:
PM> NuGet\Install-Package FolderBrowserEx -Version 1.0.1

SOURCE CODE C# :

using FolderBrowserEx;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FolderBrowserExVista
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            var dlg = new System.Windows.Forms. FolderBrowserDialog();
            dlg.ShowDialog();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            var folderBrowserDialog = new FolderBrowserEx.FolderBrowserDialog();
                    folderBrowserDialog.Title = "Select a folder";
            folderBrowserDialog.InitialFolder = @"C:\";
            folderBrowserDialog.AllowMultiSelect = false;
           
            
            if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
            {
                string result = folderBrowserDialog.SelectedFolder;
                MessageBox.Show(result);
            }
        }
    }
}

Qua từng bước trên mọi người cũng đã hiểu về thủ thuật này rồi chứ. Chúc các bạn thành công.

on Chủ Nhật, 8 tháng 10, 2023 | , , | A comment?

[CSHARP] Connect Phone via Bluetooth Application Winform

Xin chào các bạn, bài viết hôm nay mình chia sẻ các bạn source code kết nối điện thoại Android/IOS với ứng dụng c# winform.


[C#] Connect Phone via Bluetooth Application Winform

Giao diện demo ứng dụng:
[C#] Connect Phone via Bluetooth Application Winform

Ứng dụng này thực hiện các tính năng sau:

  1. Tìm kiếm các thiết bị Bluetooth
  2. Kết nối với thiết bị
  3. Thực hiện cuộc gọi từ ứng dụng
  4. Xem lịch sử cuộc gọi đến và đi theo thời gian thực
Đầu tiên, các bạn cần cài đặt thư viện để làm việc kết nối với Bluetooth từ Nuget C#.
NuGet\Install-Package InTheHand.Net.Bluetooth -Version 4.0.36

SOURCE CODE C#:
using InTheHand.Net;
using InTheHand.Net.Bluetooth;
using InTheHand.Net.Sockets;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CallInfoViaBT
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            CheckForIllegalCrossThreadCalls = false;
        }
        private Stream peerStream;
        private BluetoothClient client;

        private void button1_Click(object sender, EventArgs e)
        {
            if (client == null || client.Connected == false)
            {
                MessageBox.Show("Please make sure you have connected to device.");
                return;
            }
            string[] dialCmd = new string[6];
            dialCmd[0] = "AT+CMER\r";
            dialCmd[1] = "AT+CIND=?\r";
            dialCmd[3] = "ATD +"+TB_phoneNumber.Text+";\r";

            runCommand(dialCmd[0], peerStream);
            runCommand(dialCmd[1], peerStream);
            runCommand(dialCmd[3], peerStream);

        }

        private void runCommand(string command, Stream peerStream)
        {
            Byte[] sRes = new Byte[200];
            Byte[] dcB = System.Text.Encoding.ASCII.GetBytes(command);
            peerStream.Write(dcB, 0, dcB.Length);

        }

        public static String bytesToString(byte[] data)
        {
            String dataOut = "";
            for (int i = 0; i < data.Length; i++)
            {
                if (data[i] != 0x00)
                    dataOut += (char)data[i];
            }
            return dataOut;
        }

        private void connectButton_Click(object sender, EventArgs e)
        {
            var deviceAddr = discoveredDevices.SelectedValue.ToString();
            BluetoothAddress addr = BluetoothAddress.Parse(deviceAddr);
            BluetoothEndPoint rep = new BluetoothEndPoint(addr, BluetoothService.Handsfree);



            client.Connect(rep);
            peerStream = client.GetStream();
            backgroundWorker1.RunWorkerAsync();

            //Get call AT commands
            string[] dialCmd = new string[50];
            dialCmd[0] = "AT\r";
            dialCmd[1] = "AT+CMER=3,0,0,1,0\r";
            dialCmd[2] = "AT+CLIP=1\r";

            runCommand(dialCmd[0], peerStream);
            runCommand(dialCmd[1], peerStream);
            runCommand(dialCmd[2], peerStream);

        }

        private void closeConnection(object sender, FormClosedEventArgs e)
        {
            if (client != null && client.Connected == true)
            {
                peerStream.Close();
                client.Close();
            }

        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            while (true)
            {
                Console.WriteLine("Waiting for response..");
                Byte[] sRes = new Byte[200];
                peerStream.Read(sRes, 0, 199);
                var resStr = bytesToString(sRes);
                Console.WriteLine(resStr);
                if (resStr.Contains("CLIP"))
                {
                    onCallWithCLIP(resStr);
                }
                else if (resStr.Contains("3,1"))
                {

                    onCall(true);

                }
                else if (resStr.Contains("3,3"))
                {
                    onCall(false);
                }


                Thread.Sleep(500);
            }
        }
        private void onCallWithCLIP(string resStr)
        {
            //YES! Now I have call information.
            Console.WriteLine("Call information: " + resStr);
            char[] phoneNumber = new char[16];

            int startPhoneNoIndex = resStr.IndexOf("\"");
            int endPhoneNoIndex = resStr.IndexOf("\"", startPhoneNoIndex + 1);
            resStr.CopyTo(startPhoneNoIndex + 1, phoneNumber, 0, endPhoneNoIndex - startPhoneNoIndex - 1);
            string strPhoneNumber = new string(phoneNumber);
            strPhoneNumber = strPhoneNumber.Trim('\0');
            Console.WriteLine("Tel no: " + strPhoneNumber);


            if (!resStr.Contains("CIEV")) return;
            string[] row = { DateTime.Now.ToShortTimeString(), strPhoneNumber, "N/A" };
            var listViewItem = new ListViewItem(row);
            LWCalls.Items.Add(listViewItem);
            sendNotification("There is a new incoming call from " + strPhoneNumber);
        }
        private void onCall(bool incoming)
        {
            try
            {
                string getCurrentCallCmd = "AT + CLCC ?\r";
                Byte[] sRes = new Byte[200];
                Byte[] dcB = System.Text.Encoding.ASCII.GetBytes(getCurrentCallCmd);
                peerStream.Write(dcB, 0, dcB.Length);
                peerStream.Read(sRes, 0, 199);
                var resStr = bytesToString(sRes);
                if (resStr.Contains("+CLCC"))
                {
                    //YES! Now I have call information.
                    Console.WriteLine("Call information: " + resStr);
                    char[] phoneNumber = new char[16];
                    char[] contactName = new char[256];

                    //Let's get phone number. Listen this now: https://open.spotify.com/track/1jr1BnpXymcf2i97mTR8tJ?si=Z1xdaa5gTu6kKSg3D3X8Qg
                    int startPhoneNoIndex = resStr.IndexOf("\"");
                    int endPhoneNoIndex = resStr.IndexOf("\"", startPhoneNoIndex + 1);
                    resStr.CopyTo(startPhoneNoIndex + 1, phoneNumber, 0, endPhoneNoIndex - startPhoneNoIndex - 1);
                    string strPhoneNumber = new string(phoneNumber);
                    strPhoneNumber = strPhoneNumber.Trim('\0');
                    Console.WriteLine("Tel no: " + strPhoneNumber);


                    //Now, it is time to get contact name, if the caller is not saved in phone. Now listen this: https://open.spotify.com/track/3G2zIBotS9OUCK5uaHN2hz?si=XgF-V-JLQ26ucMLy3JCc3Q

                    int startContactIndex = resStr.IndexOf("\"", endPhoneNoIndex + 1);
                    int endContactIndex = resStr.IndexOf("\"", startContactIndex + 1);
                    resStr.CopyTo(startContactIndex + 1, contactName, 0, endContactIndex - startContactIndex - 1);
                    string strContactName = new string(contactName);
                    strContactName = strContactName.Trim('\0');
                    Console.WriteLine("Contact Name: " + strContactName);


                    string[] row = { DateTime.Now.ToShortTimeString(), strPhoneNumber, strContactName };
                    var listViewItem = new ListViewItem(row);

                    if (incoming)
                    {
                        LWCalls.Items.Add(listViewItem);
                        sendNotification("There is a new incoming call from " + strPhoneNumber);

                    }

                    else
                    {
                        LWOutCalls.Items.Add(listViewItem);
                        sendNotification("There is a new outgoing call to " + strPhoneNumber);


                    }


                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }



        }

        private void findButton_Click(object sender, EventArgs e)
        {

            discoveredDevices.DisplayMember = "DeviceName";
            discoveredDevices.ValueMember = "DeviceAddress";

            Cursor.Current = Cursors.WaitCursor;
            var devices = client.DiscoverDevices();
            discoveredDevices.DataSource = devices;
            Cursor.Current = Cursors.Default;


            warningLabel.Visible = true;
            connectButton.Enabled = true;
            discoveredDevices.Enabled = true;
            callButton.Enabled = true;

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Console.SetOut(new MultiTextWriter(new ControlWriter(richTextBox1), Console.Out));
            client = new BluetoothClient();
            warningLabel.Visible = false;
            connectButton.Enabled = false;
            discoveredDevices.Enabled = false;
            callButton.Enabled = false;
        }
        private void sendNotification(string msg)
        {
            NotifyIcon MyIcon = new NotifyIcon();
            MyIcon.Visible = true;
            MyIcon.Icon = System.Drawing.SystemIcons.Information;
            MyIcon.Text = "Call Information";
            MyIcon.BalloonTipTitle = "Call Information";
            MyIcon.BalloonTipText =msg;
            MyIcon.BalloonTipIcon = ToolTipIcon.Info;
            MyIcon.ShowBalloonTip(5000);
        }

        private void richTextBox1_TextChanged(object sender, EventArgs e)
        {
            richTextBox1.SelectionStart = richTextBox1.Text.Length;
            richTextBox1.ScrollToCaret();
        }

     
    }
    public class MultiTextWriter : TextWriter
    {
        private IEnumerable<TextWriter> writers;
        public MultiTextWriter(IEnumerable<TextWriter> writers)
        {
            this.writers = writers.ToList();
        }
        public MultiTextWriter(params TextWriter[] writers)
        {
            this.writers = writers;
        }

        public override void Write(char value)
        {
            foreach (var writer in writers)
                writer.Write(value);
        }

        public override void Write(string value)
        {
            foreach (var writer in writers)
                writer.Write(value);
        }

        public override void Flush()
        {
            foreach (var writer in writers)
                writer.Flush();
        }

        public override void Close()
        {
            foreach (var writer in writers)
                writer.Close();
        }

        public override Encoding Encoding
        {
            get { return Encoding.ASCII; }
        }
    }
    public class ControlWriter : TextWriter
    {
        private Control richTextBox;
        public ControlWriter(Control textbox)
        {
            this.richTextBox = textbox;
        }

        public override void Write(char value)
        {
            richTextBox.Text += value;
        }

        public override void Write(string value)
        {
            richTextBox.Text += value;
        }

        public override Encoding Encoding
        {
            get { return Encoding.ASCII; }
        }
    }
}

Như vậy là xong, các bạn có thể tải source code về test thử nhé.
Chúc các bạn thành công.

DOWNLOAD SOURCE CODE



PASSWORD UNZIP: HUNG.PRO.VN

on Thứ Bảy, 7 tháng 10, 2023 | , , , | A comment?

Tìm Hiểu Về Net Framework Là Gì?

Net Framework là gì? Tìm hiểu về Microsoft .NET Framework

Net Framework là công cụ và là nền tảng lập trình có mặt trong hệ điều hành Windows, được sáng tạo bởi công ty nổi tiếng Microsoft. Là phần mềm tương đối phổ biến, Net Framework đảm nhiệm việc điều khiển hệ thống phần mềm. Chức năng chính của chúng là đảm bảo an toàn hệ thống, quản lý bộ nhớ dữ liệu cũng như xử lý các lỗi liên quan.

Để hiểu được .Net Framework là gì chúng ta cần tìm hiểu từ chức năng cơ bản của chúng. Về cơ bản, Net Framework bao gồm thư viện code được chia sẻ mang tên là Framework Class Library (FCL). Các bit của code nằm trong thư viện chia sẻ (shared library) có khả năng thực hiện tất cả các loại chức năng khác biệt. Công cụ này hỗ trợ xây dựng các chương trình phần mềm, tham gia lập trình cho giao diện máy chủ, kết nối cơ sở dữ liệu, giao tiếp giữa các mạng và còn hơn thế nữa.

Chúng ta có thể ví dụ rằng, một nhà phát triển muốn ứng dụng được lập trình để truy vấn một địa chỉ IP khác trên internet. Nếu như bình thường, nhà phát triển đó phải tự viết code, bit cũng như những phần giải thích ý nghĩa của kết quả truy vấn, thì giờ đây nhờ thư viện thực hiện chức năng chứa sẵn code mà công việc của họ sẽ được rút gọn bớt.

Ví dụ trên chỉ là một phần nhỏ trong lợi ích lớn lao mà Net Framework mang lại. Phần mềm này chứa hàng trăm nghìn đoạn code, cho phép các nhà phát triển làm việc thuận tiện và dễ dàng hơn. Công đoạn viết các lớp code đầu của một số chức năng phổ biến trên ứng dụng sẽ được lưu trữ sẵn trong Net Framework, nhờ đó mà những nhà lập trình sẽ tập trung hơn vào các đoạn code chuyên sâu của ứng dụng, như giao diện sử dụng hoặc các chức năng nâng cao.
 
Việc dùng chung một framework để chia sẻ đoạn code cho nhiều người dùng cũng góp phần tạo nên một số quy chuẩn giữa các ứng dụng. Việc các công năng phổ biến được tối ưu hóa giúp các nhà phát triển hiểu được về cách chương trình hoạt động dễ dàng nhất. Không phải ngẫu nhiên mà những thứ như hộp thoại Open hay Save As đều hoạt động y hệt nhau ở từng ứng dụng.

Lịch sử phát triển của Net Framework là gì?

Net Framework ra mắt vào năm 2002, công cụ này được sử dụng cho các hệ điều hành như: Windows 98, NT 4.0, 2000 và XP. Sau một thời gian dài, Microsoft đã dừng hỗ trợ chính thức cho phiên bản này vào tháng 7/2009.

Tiếp đến là phiên bản Net Framework 1.1 ra mắt người dùng vào năm 2003. Với những nâng cấp nổi trội không thể không kể tới như tích hợp hỗ trợ mobile ASP.NET, dùng sandbox khi vận hành các ứng dụng từ Internet để chắc chắn các vấn đề bảo mật, …

Net Framework đã không ngừng phát triển và nghiên cứu bằng chứng là sự ra đời liên tiếp của các phiên bản từ 2.0 đến 4.5 hằng năm. Hiện tại, Net Framework là đã phát hành phiên bản 4.5 vào năm 2012.

Ưu nhược điểm của Net Framework

Dưới đây là một số ưu và nhược điểm của Net Framework, bao gồm:

Ưu điểm

Thư viện lập trình lớn: Lợi ích lớn nhất mà .Net Framework mang lại chính là việc tạo ra môi trường chung và mang lại hiệu suất tối ưu việc tạo lập, xây dựng các ứng dụng web; Truy cập, kết nối các CSDL, cấu trúc dữ liệu; Lập trình giao diện,… .

Đa ngôn ngữ: Dù là loại ngôn ngữ nào như C#, C++, Visual Basic, bạn cũng có thể thoải mái viết, nhưng vẫn luôn đảm bảo khả năng tích hợp. Các đoạn code này sẽ được dùng cho phần mềm tương thích với rất nhiều phần cứng mà Net Framework hỗ trợ.

Nǎng suất làm việc cao: Lập trình, thiết kế ứng dụng với .NET không lãng phí nhiều thời gian bởi nó cung cấp sẵn rất nhiều yếu tố dùng trong thiết kế. Bạn chỉ cần hiểu rõ cách dùng và tùy biến các đoạn code có sẵn này cho tương thích với dự án của bạn, việc lập trình sẽ nhanh chóng và dễ dàng hơn rất nhiều.

Biến đổi linh hoạt nhờ kiến trúc “ghép nối lỏng”: .NET được được tạo ra với khả năng tùy biến linh hoạt nhờ cấu trúc ‘ghép nối lỏng’. Điều này mang lại nhiều điểm nổi trội về mặt năng suất.

Bảo mật cao: .NET có phần kiến trúc bảo mật được xây dựng theo hình thức từ dưới lên. Việc này hỗ trợ bảo vệ dữ liệu cũng như các ứng dụng tránh những mối nguy hại từ hacker bằng mô hình bảo mật tinh vi được gọi là evidence-based.

Tận dụng các dịch vụ sẵn có trong hệ điều hành: Windows có rất nhiều dịch vụ có khả năng vận hành trên tất cả nền tảng gồm: truy cập dữ liệu, mô hình dạng đối tượng thành phần, giao diện người dùng tương tác, bảo mật tích hợp và cả giám sát giao dịch. Cũng từ những lợi thế đó .NET để đơn giản hóa cách dùng, hỗ trợ lập trình trên công cụ này trở nên đơn giản hơn.

Ngoài ra, Microsoft phát triển phần mềm Net Framework rất tốt, hầu như không gặp bất kỳ vấn đề gì trong cách vận hành.

Nhược điểm

Mặc dù có khả năng tương tích với khá nhiều phần cứng, nhưng Net Framework chưa thể giúp ích được gì nếu máy tính của bạn chưa cài đặt công cụ này. Hiểu một cách đơn giản, bạn cần phải cài đặt Net Framework trên PC để chạy được những chương trình được thiết kế dựa trên nền tảng Net Framework.
Những nhầm lẫn thường gặp của Net Framework

Ngay cái tên “Net Framework” của Microsoft đã dễ tạo nên sự nhầm lẫn đối với người sử dụng. Ở đây chúng ta cần biết rằng, khái niệm framework thực chất là một tập hợp API (Application Programming Interface – giao diện lập trình ứng dụng) và một thư viện chia sẻ (shared library) code. Nhờ thư viện chung này mà các nhà phát triển có thể dùng một số đoạn code quen thuộc khi phát triển ứng dụng thay vì phải tự viết code.

Ngoài chức năng chính là framework – thư viện chia sẻ code, Net Framework còn cung cấp một môi trường để chạy thử ứng dụng. Môi trường này tạo ra một sandbox – tương tự như máy ảo, là nơi để các ứng dụng chạy. Thực ra đây không phải điều gì quá mới lạ, Một số nền tảng phát triển khác như Java và Ruby trên Rails cũng làm điều tương tự,
 
Với Net Framework, môi trường này có tên là Common Language Runtime (CLR). Khi người dùng cho chạy một ứng dụng, code cho ứng dụng đó sẽ được biên dịch thành ngôn ngữ máy tại thời gian chạy, từ đó sẽ được thực thi trên sandbox. CLR còn có một số chức năng hữu ích khác, có thể kể đến như quản lý bộ nhớ và bộ vi xử lý, xử lý các trường hợp ngoại lệ của chương trình và quản lý bảo mật. Nói tóm lại, môi trường chạy ứng dụng là cách để lấy ứng dụng từ phần cứng thực tế mà ứng dụng đang chạy.
Cũng có một số vấn đề được đặt ra đối với các nền tảng sử dụng .Net Framework. Mặc dù nền tảng này được thiết kế nhằm hỗ trợ nhiều phần cứng khác nhau, tuy nhiên do tính chất độc quyền, Net Framework ban đầu chỉ được sử dụng chủ yếu cho các ứng dụng hệ điều hành Windows.

Tuy nhiên, điều này lại gây nên một nhầm lẫn khác là Net Framework chỉ xuất hiện trên Windows. Thực tế, Microsoft đã bổ sung thêm một số phiên bản khác nhau để hỗ trợ giải quyết vấn đề nói trên. Ví dụ, Mono là một dự án nguồn mở và miễn phí, với mục đích cung cấp sự tương thích giữa các ứng dụng Net Framework với các nền tảng khác, đặc biệt dành cho hệ điều hành Linux. Ngoài ra, Microsoft còn triển khai Net Core – một dạng framework mã nguồn mở và miễn phí, mang đến những ứng dụng nhẹ, module đến nhiều nền tảng.

on Thứ Ba, 3 tháng 10, 2023 | , , , | A comment?