Arquivo de abril, 2014

Visual – ToolTip e cl_salv_tooltips – Abap

Publicado: 30 de abril de 2014 em Abap

Tooltip é um elemento comum de interface gráfica GUI, também conhecida como dica de contexto é aquela moldura pop up que abre quando você passa o mouse sobre um elemento da interface (normalmente uma palavra em um texto) e que contém uma explicação adicional sobre aquele elemento que recebeu o ponteiro do mouse sobre ele. É utilizado em conjunto com um cursor, normalmente um ponteiro do mouse. O usuário paira o cursor sobre um item, sem clicar nele, e uma pequena “caixa” irá aparece com informações complementares relativas a este item.

ToolTip - Screen Painter

ToolTip – Screen Painter

ToolTip

Para utilizar o tooltip no Screen Painter basta preencher a propriedade do componente com a dica requerida.

cl_salv_tooltips

O objeto de dica de ferramenta contém as seguintes informações: o tipo de dica de objeto que é para qual elemento a dica pode ser processada, o indicador para o elemento e o texto que é apresentado como dica.

Para um exemplo desta classe utilize o programa de exemplo do Netweaver: BCALV_DEMO_TOOLTIP.

Mais informações sobre tooltips: http://help.sap.com/saphelp_nw70/helpdata/en/1f/6dee408a63732ae10000000a155106/content.htm?frameset=/en/1f/6dee408a63732ae10000000a155106/frameset.htm

Exemplo:

Neste exemplo usamos a propriedade tooltip do elemento PushButton do Screen Painter, para usar o programa abaixo crie uma tela, um evento PBO e o campo OK_CODE e preencha o campo function code para o botão como F_BTN1,  para exemplo da classe use o programa citado. acima.

Abap

*&---------------------------------------------------------------------*
*& Report  ZTOOLTIP
*&
*&---------------------------------------------------------------------*
*& Desenvolvimento Aberto
*& ToolTip
*&---------------------------------------------------------------------*

REPORT  ZTOOLTIP.

DATA: ok_code LIKE sy-ucomm,
      clique_ok LIKE sy-ucomm.

CALL SCREEN 100.

MODULE STATUS_0100 OUTPUT.
*  SET PF-STATUS 'xxxxxxxx'.
*  SET TITLEBAR 'xxx'.

* limpa evento
  clique_ok = ok_code.
  CLEAR ok_code.

* Eventos dos botões ou teclas
  CASE clique_ok.

    WHEN 'F_BTN1'.
      LEAVE PROGRAM.

  ENDCASE.

ENDMODULE.                 " STATUS_0100  OUTPUT

 

Tooltip é um elemento comum de interface gráfica GUI, também conhecida como dica de contexto é aquela moldura pop up que abre quando você passa o mouse sobre um elemento da interface (normalmente uma palavra em um texto) e que contém uma explicação adicional sobre aquele elemento que recebeu o ponteiro do mouse sobre ele. É utilizado em conjunto com um cursor, normalmente um ponteiro do mouse. O usuário paira o cursor sobre um item, sem clicar nele, e uma pequena “caixa” irá aparece com informações complementares relativas a este item.

ToolTip - Tkinter

ToolTip – Tkinter

ToolTip

A classe ToolTip fornece um widget de dica flexível para Tkinter.

Download

http://tkinter.unpythonic.net/wiki/ToolTip

Exemplo:

Neste exemplo utilizaremos uma classe de fonte aberto para criar um Widget ToolTip, salve a classe no diretório de sua aplicação ou nos diretórios do Python.

Python

#!/usr/bin/env python
# -*- coding: latin-1 -*-
# Desenvolvimento Aberto
# ToolTip.py

# importa modulos
import Tkinter
from ToolTip import ToolTip

# Cria formulario
formulario = Tkinter.Tk(className='Tk - ToolTip')

# Cria componentes
rotulo = Tkinter.Label(formulario, text="Pare o cursor em cima do Button por alguns segundos")

botao = Tkinter.Button(formulario, text='Aperte Aqui !!!', command=formulario.quit)

# Cria Dica (Tooltip)
dica = ToolTip(botao, follow_mouse=1, text="Desenvolvimento Aberto, Clique para sair do programa.")

# Posiciona componentes
rotulo.pack(padx=20, pady=10)
botao.pack(pady=10)

# Loop do Tcl
formulario.mainloop()

Tooltip é um elemento comum de interface gráfica GUI, também conhecida como dica de contexto é aquela moldura pop up que abre quando você passa o mouse sobre um elemento da interface (normalmente uma palavra em um texto) e que contém uma explicação adicional sobre aquele elemento que recebeu o ponteiro do mouse sobre ele. É utilizado em conjunto com um cursor, normalmente um ponteiro do mouse. O usuário paira o cursor sobre um item, sem clicar nele, e uma pequena “caixa” irá aparece com informações complementares relativas a este item.

CToolTipCtrl

CToolTipCtrl

CToolTipCtrl

Encapsula a funcionalidade de um controle dica de ferramenta“, uma pequena janela pop-up que exibe uma única linha de texto que descreve a finalidade de uma ferramenta em um aplicativo.

PreTranslateMessage

Você pode efetuar um método Override para substituir esta função para filtrar mensagens de janela antes de serem enviados para Windows.

Visual Studio

Para criar um controle ToolTip para um dialogo MFC em C++ siga os seguintes passos:

  1. Crie um novo projeto MFC Dialog Based.
  2. Coloque no dialogo um componente Static Text e um componente Button, crie uma variável para o botão chamada m_botao.
  3. Disponha os componentes no dialogo conforme a imagem abaixo:

    CToolTipCtrl - Design

    CToolTipCtrl – Design

  4. Declare o método Override para a mensagem PreTranslateMessage e crie um objeto CToolTipCtrl para a classe de seu dialogo, use o primeiro código para se basear.
  5. Complete seu código gerado automaticamente para a implementação da classe, use o segundo código para se basear.

Exemplo:

Neste exemplo usamos o objeto CToolTipCtrl para exibir uma dica para o usuário ao pairar o cursor do mouse sobre o botão, interceptando a mensagem e exibindo o texto da dica na mensagem do Windows PreTranslateMessage.

C++

Classe – Definição (.h)


// tooltipcppDlg.h : header file
//

#pragma once
#include "afxwin.h"

class CtooltipcppDlg : public CDialogEx
{

public:
	CtooltipcppDlg(CWnd* pParent = NULL);	

	enum { IDD = IDD_TOOLTIPCPP_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);

protected:
	HICON m_hIcon;

	// Desenvolvimento Aberto
	// Declara metodo de menssagem
	BOOL PreTranslateMessage(MSG* pMsg);
	
	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:

	// Declara componente tooltip
	CToolTipCtrl* m_pToolTip;

	CButton m_botao;
};

Classe – Implementação (.cpp)


// tooltipcppDlg.cpp : implementation file
//

#include "stdafx.h"
#include "tooltipcpp.h"
#include "tooltipcppDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

CtooltipcppDlg::CtooltipcppDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CtooltipcppDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CtooltipcppDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_BUTTON1, m_botao);
}

BEGIN_MESSAGE_MAP(CtooltipcppDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
END_MESSAGE_MAP()


BOOL CtooltipcppDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
		
	SetIcon(m_hIcon, TRUE);			
	SetIcon(m_hIcon, FALSE);		

	// Desenvolvimento Aberto
	// Inicializa objeto tooltip e define suas propriedades	
	
	// Cria objeto tooltip 
	m_pToolTip = new CToolTipCtrl;

	if (!m_pToolTip->Create(this))
	{	
		return TRUE;
	}

	// Define objeto para a dica
	m_pToolTip->AddTool(&m_botao, 
		L"Desenvolvimento Aberto - Clique neste botão para executar uma ação.");
	
	// Ativa tooltip
	m_pToolTip->Activate(TRUE);

	return TRUE;  
}

void CtooltipcppDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); 

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
				
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;
				
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

HCURSOR CtooltipcppDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

// Desenvolvimento Aberto
// Cria override da menssagem do windows

BOOL CtooltipcppDlg::PreTranslateMessage(MSG* pMsg)
{
	m_pToolTip->RelayEvent(pMsg);

	return CDialog::PreTranslateMessage(pMsg);
}

Visual – ToolTip – C#

Publicado: 29 de abril de 2014 em C#

Tooltip é um elemento comum de interface gráfica GUI, também conhecida como dica de contexto é aquela moldura pop up que abre quando você passa o mouse sobre um elemento da interface (normalmente uma palavra em um texto) e que contém uma explicação adicional sobre aquele elemento que recebeu o ponteiro do mouse sobre ele. É utilizado em conjunto com um cursor, normalmente um ponteiro do mouse. O usuário paira o cursor sobre um item, sem clicar nele, e uma pequena “caixa” irá aparece com informações complementares relativas a este item.

ToolTip

ToolTip

ToolTip

Representa uma pequena janela pop-up retangular que exibe uma breve descrição do propósito de um controle quando o usuário posicionar o ponteiro do mouse sobre o controle.

Exemplo:

Neste exemplo usamos o objeto ToolTip para exibir uma dica para o usuário ao pairar o cursor do mouse sobre o botão.

C#

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 Dicas
{
    public partial class Form1 : Form
    {
        // Declara componentes
        Label rotulo;
        Button botao;
        ToolTip dicas;
                
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            // Define propriedades do formulario
            this.Text = "DA - ToolTip";
            this.Size = new Size(300, 150);

            // Cria componentes
            rotulo = new Label();
            botao = new Button();
            dicas = new ToolTip();

            // Define tamanho e localização
            rotulo.Size = new Size(300, 20);
            rotulo.Location = new Point(0, 20);
            botao.Location = new Point(10, 50);

            // Define textos
            rotulo.Text = "Pare o cursor em cima do botão por alguns segundos";
            botao.Text = "Aperte Aqui!";

            // Alinha texto
            rotulo.TextAlign = ContentAlignment.TopCenter;

            // Define propriedades de tempo para o componente de dicas
            dicas.AutomaticDelay = 2000;
            dicas.AutoPopDelay = 3000;
            dicas.ReshowDelay = 500;
            dicas.ShowAlways = true;

            // Define dica para o componente escolhido
            dicas.SetToolTip(botao, "Desenvolvimento Aberto - " +
                                    "Clique neste botão para executar uma ação.");

            // Adiciona componentes ao formulario
            this.Controls.Add(rotulo);
            this.Controls.Add(botao);

        }
       
    }
}

Visual – JToolTip – Java

Publicado: 29 de abril de 2014 em Java

Tooltip é um elemento comum de interface gráfica GUI, também conhecida como dica de contexto é aquela moldura pop up que abre quando você passa o mouse sobre um elemento da interface (normalmente uma palavra em um texto) e que contém uma explicação adicional sobre aquele elemento que recebeu o ponteiro do mouse sobre ele. É utilizado em conjunto com um cursor, normalmente um ponteiro do mouse. O usuário paira o cursor sobre um item, sem clicar nele, e uma pequena “caixa” irá aparece com informações complementares relativas a este item.

JToolTip

JToolTip

JToolTip

Usado para exibir uma dica” para um componente. Normalmente componentes fornecem api para automatizar o processo de utilização de dicas de ferramentas. Por exemplo, qualquer componente Swing pode usar o método JComponent setToolTipText para especificar o texto para uma dica de ferramenta padrão. Um componente que quer criar uma exibição personalizada dica de ferramenta pode substituir o método createToolTip de JComponent e usar uma subclasse dessa classe.

Exemplo:

Neste exemplo usamos o método setToolTipText para exibir uma dica para o usuário ao pairar o cursor do mouse sobre o botão.

Java

import java.awt.Container;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Dicas {

	// Declara componentes
	JLabel rotulo;
	JButton botao;

	// Declara variaveis
	String dica = "Desenvolvimento Aberto - " +
	              "Clique neste botão para executar uma ação.";			     

	public Container criaPainel()
	{
		// Cria painel
		JPanel painel = new JPanel();

		// Define layout
		painel.setLayout(new BoxLayout(painel, BoxLayout.PAGE_AXIS ));
		painel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
		painel.setOpaque(true);

		// Cria componentes
		rotulo = new JLabel("Pare o cursor em cima do botão por alguns segundos");
		botao  = new JButton("Aperte Aqui!");

		// Cria tooltip
		botao.setToolTipText(dica);

		// Adiciona componentes ao painel
		painel.add(rotulo);
		painel.add(Box.createVerticalStrut(10));
		painel.add(botao);

		return painel;
	}

	public static void criaGUI()
	{
		// Cria formulario
		JFrame formulario = new JFrame("DA - ToolTip");
		formulario.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		// Cria instancia da classe
		Dicas dicas = new Dicas();

		// Define painel de conteudo
		formulario.setContentPane(dicas.criaPainel());

		// Define propriedades do formulario
		formulario.pack();
		formulario.setVisible(true);

	}

	public static void main(String[] args)
	{
		// Thread do swing
		javax.swing.SwingUtilities.invokeLater(new Runnable() {

			@Override
			public void run()
			{
				// Mostra GUI
				criaGUI();
			}

		});

	}

}

O que a linguagem de programação Delphi tem em comum com Java e C#? A resposta é tudo? Ou nada? Quem sabe!. Estranho? Com certeza! E a resposta correta depende da versão do Delphi do qual estamos nos referindo. Ou não?

O Delphi nasceu em 1995 como uma linguagem de programação Object Pascal para o Windows 16 bits e foi o primeiro a ser descrito como ambiente RAD (em português, Desenvolvimento Rápido de Aplicações), seu nome faz alusão ao banco de dados Oracle, pois na mitologia grega o Oraculo (Oracle) podia ser encontrado no templo de Delphi.

Delphi - Win32

Delphi – Win32

O Delphi se difundiu pelo mundo na sua versão para Windows 32 bits,  justamente por fazer realmente o que prometia, era rápido para desenvolvimento em grandes equipes, podia se conectar com qualquer banco de dados e de vários modos diferentes, além de possuir uma gama de componentes de todos os tipos, desde os Open Source, como o famoso pacote de componentes Russo chamado RX, até componentes empresariais relacionado a dados e ao visual da aplicação como o InfoPower e 1st Class da empresa Woll2Woll.

O Delphi também possuía vários componentes para relatório onde podia-se  utilizar o poder da sua conexão com o banco de dados Oracle, unidos aos recursos de seus componentes, também possuía integração com o gerador de relatório mais famoso do mundo o Cristal Reports que hoje pertence a SAP.

Outro ponto forte do Delphi é que era possível programar rotinas em Assembler dentro do Object Pascal apenas abrindo um bloco ASM e dizendo direto ao hardware o que o desenvolvedor gostaria de fazer. O Delphi também possuía várias rotinas Assembler como parte de seus comandos como o caso do comando Abort, para ver estas rotinas bastava clicar em cima do comando em questão escrito de qualquer Unit pascal  e pressionando o botão Control (CTRL + Click)  e automaticamente você seria levado ao código que o originava, assim como nas IDEs de hoje em dia.

Assembler Delphi: http://docwiki.embarcadero.com/RADStudio/XE3/en/Using_Inline_Assembly_Code

Com o “Boom” do Linux em 2001 foi lançada uma versão para esta plataforma chamada Kylix,  com o lançamento do Delphi 8 a linguagem passou a suportar o .NET Framework, podendo-se escrever programas C# direto de sua IDE, mas não vingou e  muitas empresas estacionaram seu desenvolvimento na versão 7 do Delphi. O Delphi hoje é marca registrada da empresa Embarcadero e está na sua versão XE10 (emprestando a estratégia de versão do Windows 10) no qual pode-se desenvolver aplicações verdadeiramente nativas para Windows, Mac, Android e iOS a partir de uma única base de código.

Delphi 7 - Win32

Delphi 7 – Win32

Desenvolvimento em Delphi vale a pena migrar para Java ou C#?

Bom,  então, para quem migrou da versão 7 do Delphi para suas versões superiores e utilizou o suporte a plataforma .Net não temos muito o que falar, pois C# lembra muito o Java que por sua vez bebeu da fonte do C++ e assim por diante, mas para aqueles que continuam desenvolvendo em Delphi para Win32 a coisa é bem diferente.

Existe até uma URL estratégica da Embarcadero preparada para as pesquisas do Google:

UpGrade Delphi 7 para XE10: http://www.embarcadero.com/br/products/rad-studio/upgrade-from-delphi7

Programas escritos em Delphi 7, suas versões anteriores ou versões superiores mas utilizando projetos de código nativo ainda são comuns e a pergunta mais frequente é se vale a pena migrar para Java ou C#?

A resposta é simples, sim! Vale a pena mudar!

Por que ?

Ao contrario do que a maioria pensa (que me digam os proprietários de software houses que ainda desenvolve em Delphi código nativo)  desenvolver para Win32 exige um conhecimento muito técnico das APIs do Windows, apesar do Delphi transformar esta programação em uma tarefa extremamente fácil (vide Visual Studio MFC C++ para Win32) o resultado algumas vezes pode não ser aquele desejado pelos proprietários de software house, nem pelos clientes e nem pelos programadores.

Na pratica existem muitos programas escritos em Delphi para Win32 que são lentos, mesmo usando o melhor banco de dados do mundo, o Oracle, sem entrar no mérito das melhores praticas para um banco de dados. Muitos programas geram erros de memoria sozinhos, apenas com o usuário o utilizando, são difíceis de dar manutenção e não são projetados para o crescimento da base de dados, e pasmem, existem programas que param de funcionar devido a lentidão quando utilizados em bases de dados de grande porte (entrando no mérito das melhores praticas para um banco de dados), gerando para as empresas uma legião de clientes insatisfeitos, se identificou?

Mas o problema não é do Delphi e nem das APIs do Windows e sim da técnica dos programadores principalmente de programas que já foram migrados do Cobol, Clipper, DataFlex entre outras linguagens na qual se utiliza bases de dados relativamente grandes. Um erro comum era não conhecer o sistema operacional e não usar Dlls e ActiveX, criando Units de código pascal para as bibliotecas e programas reutilizáveis que eram referenciadas entre si e compiladas junto com o executável o tornando enorme, além disto, necessitando deste modo criar grande quantidade de procedimentos e funções publicas para estas Units ou Forms também referenciados (quando a convenção para qualquer linguagem orientada a objeto diz que você deve sempre criar métodos privados e usar métodos públicos somente quando realmente for necessário). A consequência deste tipo de programação é sem duvida, vazamento de memoria (Memory Leak), visto que apenas o Delphi com suporte ao .NET Framework possui o Garbage Collector, além de códigos fonte crescendo desordenadamente ao longo dos anos, sem contar outros inúmeros conceitos da programação para Win32 que continuaram sendo completamente ignorados.

Dinamic-Link Library: http://msdn.microsoft.com/en-us/library/windows/desktop/ms681914(v=vs.85).aspx

Component Object Model: http://msdn.microsoft.com/en-us/library/windows/desktop/ms694363(v=vs.85).aspx

Delphi ActiveX Framework: http://docwiki.embarcadero.com/RADStudio/XE3/en/Overview_of_COM_Technologies

Memory Leak Delphi: http://delphi.about.com/od/oopindelphi/a/memoryleak.htm

Para quem não teve estes problemas ainda possui um software plenamente funcional, rápido e com um pouco mais de trabalho pode se desenvolver qualquer coisa que é feita hoje em dia, pois a Microsoft garante a compatibilidade da API Win32 (conceito que significa código nativo e não só para 32 bits). Assim como o modelo de  programas em Delphi escritos em código nativo, nos dias hoje a Microsoft disponibiliza este tipo de  ferramenta apenas para C++, e este tipo de programação não pode ser desenvolvida à partir de uma versão Express do Visual Studio, pois a aplicação nativa é ideal para softwares coorporativos por ser consideravelmente mais rápida do que aplicações utilizando o framework.

Código Nativo – Win32 : http://msdn.microsoft.com/pt-br/library/hh875053.aspx

Delphi possui a melhor IDE RAD de todos os tempos, suporta vários tipos de conexões incluindo os melhores bancos de dados do mundo, é multi-plataforma, possui código nativo com acesso pleno a API de plataforma, incluindo plataformas mobiles.

Embarcadero: https://www.embarcadero.com/br

Delphi Language: http://docwiki.embarcadero.com/RADStudio/XE3/en/Language_Overview

Rad Studio XE7

RAD Studio XE7

Migração Delphi – Java ou C#

Muitos proprietários e gerentes de TI se deixam levar por toda propaganda em torno das linguagens Java e C#, o que você deve lembrar é que você esta lidando com a Oracle e a Microsoft e um orçamento enorme para marketing mundial, isto significa que os softwares principais ou seja, produtos de primeira linha para o segmento empresarial que fazem praticamente tudo e estão no topo da tecnologia, os “ERPs” das grandes empresas fornecidos pela Oracle e Microsoft que provavelmente são concorrentes direto, senão em um todo em algum módulo do produto que você planeja desenvolver e possivelmente são vendidos por um valor muito maior do que seu produto final será, estes produtos topo de linha não foram desenvolvidos e nem utilizam Java e .NET, o Oracle JDEdwards utiliza Event Rule Language, C e C++ e o Microsoft Dynamics AX (C++) utiliza sua IDE MorphX e a linguagem X++ e foi desenvolvido originalmente pela IBM, então você não deve tornar nenhuma das marcas registradas seu time do coração antes de conhecer as mesmas razoavelmente. Não pense que você vai desenvolver o próximo JDE ou Dynamics usando Java ou C#, até porque os bancos de dados renomados fabricados pelas mesmas empresas detentoras dos ERPs possuem Features exclusivas para os mesmos e assim também acontece com o SAP R/3 que é líder no mercado empresarial e a Oracle e a Microsoft se orgulham em dizer que seus bancos de dados são certificados para as aplicações SAP.

É claro que você pode desenvolver ótimos e robustos softwares com as linguagens Java e C# mas tenha em mente que investir em infraestrutura, conhecimento técnico e funcional é muito importante, por isto se você é testemunha de problemas descritos no tópico acima simplesmente migrar para uma destas linguagens por si só não vai resolver seu problema, muito pelo contrario, Java é baseado em C++ e C# é baseado em Java, assim o conceito de objetos, classes, coleções, iteradores entre outros, demanda uma curva de aprendizado relativamente maior que o aprendizado exigido pela linguagem Object Pascal, sem contar que o programador também deve conhecer como funciona o sistema operacional em questão independente da linguagem ser ou não multi plataforma.

Dependendo do tipo de projeto, hoje, também vale a pena utilizar linguagens que vem ganhando muito espaço no mercado internacional e no Brasil, como Ruby e Python que possuem uma comunidade muito ativa. No exterior Python é ensinado a crianças nas escolas e muitos a veem como uma linguagem do futuro. Estas linguagens são multi plataforma, muito versáteis e puramente orientadas a objeto, apesar do Python não possuir oficialmente esta classificação é bem similar ao Ruby, na verdade Ruby que foi inspirado em Python, e de qualquer modo Python e Ruby possuem uma orientação a objeto mais pura que Java e C# pois não possuem tipos primitivos possibilitando cortar alguns caminhos na hora da codificação, além do beneficio de que as duas linguagens possuem uma sintaxe simples e minimalista, fazem a mesma coisa requerendo muito menos linhas de código e ainda por cima de um modo mais fácil.

Já o Java e o C# herdam a sintaxe e conceitos do C++, inclusive o C# trouxe do C++ muita coisa que o Java aboliu, como ponteiros e Structs, as duas linguagens na pratica são muito similares e ambas já são linguagens conceituadas. Uma vantagem é que Java, Ruby e Python são linguagens que possuem muitos frameworks de código aberto sob diversas licenças, evoluem mais rápido do que o C# que vai incorporar as novidades só em sua próxima versão ou na próxima versão do Windows que agregará novas tecnologias, muitas delas vindas ou inspiradas no código aberto, como vários frameworks Java que também foram escritos para C# mais tarde, e o próprio ASP.NET MVC que foi e ainda é altamente influenciado pelo framework Rails.

Entretanto a Microsoft já se mobilizou para tentar mudar esta situação criando uma serie de medidas, lançando uma versão comunitária do Visual Studio, adotando o Python e outras linguagens e as integrando ao Visual Studio, firmando parcerias com empresas como a Apache incorporando o Apache Córdoba e a empresa Xamarim que patrocina o Mono (Linux) e é proprietária da plataforma Xamarim (OS X e Android), outra medida também foi abrir o código fonte da tecnologia ASP.NET tornando seus frameworks abertos sob a licença Apache, para que possam sofrer mais influencias da comunidade de código aberto, pretende também em um futuro próximo, abrir o código do núcleo do .Net Framework para que se torne autossuficiente em outras plataformas. Influencia esta que o Java e outras linguagens já possuem e atuam fortemente em todas as plataformas (Unix, Linux, Windows, OS X e diversos devices), inclusive na tecnologia Cloud, onde a Oracle proprietária do Java há tempos já lançou o primeiro sistema operacional exclusivo para as nuvens, o Oracle Solaris 11, em contrapartida as varias distribuições Linux Enterprise como a RedHat também estão investindo fortemente na plataforma Cloud, como por exemplo a plataforma hibrida OpenShift que suporta serviços em varias linguagens e bancos de dados diferentes, enquanto a Microsoft foca exclusivamente na sua tecnologia Azure, MSSQL Server, na interoperabilidade com o sistema operacional Linux Suse Enterprise e em suas novas parcerias.

Durante todas estas reviravoltas tecnológicas no universo do código aberto e no mundo proprietário, batalhas judiciais pelas patentes de softwares e devices, o Delphi apenas corre atrás das velhas novidades, ainda tentando mover usuários (sem perde-los) de sua plataforma Win32 para as suas novas plataformas proprietárias (livre somente de royalts) que competem com vários outros frameworks mais atuais, muitos deles de código aberto e ou gratuitos.

Conectividade Delphi: http://www.embarcadero.com/br/products/delphi/connect

Uma das mais famosas bibliotecas C++ no qual Java e C# foram baseados:

Standard Template Library: http://msdn.microsoft.com/en-us/library/c191tb28.aspx

STL/CLR Library: http://msdn.microsoft.com/en-us/library/bb385954.aspx

JCF – Framework: http://docs.oracle.com/javase/tutorial/collections/intro

No Brasil a linguagem de programação C# é a queridinha das empresas de pequeno e médio porte, isto é devido as diversas ações que a Microsoft executa no mercado nacional com seus programas, entre eles as certificações com escolas credenciadas, Microsoft Partners e inúmeras convenções e encontros, já o Java atua soberano no mercado de software para Main Frames e Devices, desenvolve-se em Java também dentro de softwares de grande porte, incluindo softwares da Oracle, IBM, Google e SAP, como no banco de dados Oracle e IBM DB2, que rodam rotinas em Java, além destas quatro companhias também possuírem uma IDE exclusiva para programar em Java, elas são NetBeans (Oracle), Eclipse (IBM), Android Studio (Google) e NetWeaver para Java da SAP, em sua nova tecnologia para as nuvens SAP HANA a SAP adota a IDE Eclipse como sua nova plataforma de desenvolvimento. Sem contar outras inúmeras tecnologias profissionais e servidores de aplicações Enterprise para Java como Oracle WebLogic, IBM WebSphere, TomCat da Apache, JBoss da Red Hat.

Fora do Brasil o C# esta qualificado com apenas 7.4% no ranking de linguagens mais procuradas pelas empresas, enquanto Java possui 19,6%, segundo o site CodeEval o ranking das linguagens mais populares de 2015 são: Ranking Code Eval.

Já no Tiobe Index 2015, a linguagem Java aparece em segundo lugar, C# ocupa a quarta posição enquanto Delphi desde 2013 se localiza abaixo da decima sétima posição, você pode conferir o ranking mensal da Tiobe aqui: Tiobe Index 2015. Nos dois índices Java e C# ocupam posições similares no ranking.

Uma ótima ilustração para os parágrafos acima pode ser utilizando a ótica da empresa SAP (Lider mundial de software corporativo). Seu principal produto o SAP R/3 para grandes empresas utiliza opcionalmente Java como linguagem de desenvolvimento e também no núcleo algumas de suas aplicações, já seu produto para pequenas empresas chamado Business One utiliza .NET. Independe dos motivos quem conhece as duas aplicações sabe da diferença enorme da tecnologia entre elas.

Para uma comparação técnica completa entre Java e C#, utilize o link a seguir:

C# for Java Developers: http://msdn.microsoft.com/en-us/library/ms228358(v=vs.90).aspx

Legados do Delphi

Java

Se tratando do Java seu conceito de objetos e sintaxe são baseados em C++ e em bibliotecas como a STL (Standard Template Library), mas o Delphi deixou um importante legado que é a IDE visual do NetBeans, originalmente denominada Xelfi e desenvolvida na República Tcheca em 1996. O objetivo era escrever uma IDE Java similar ao Delphi. O Xelfi foi a primeira IDE escrita em Java e posteriormente comprada pela SUN, que hoje pertence a Oracle e os exemplos oficiais são escritos para está IDE, inclusive a plataforma Java SEEE podem ser baixadas em pacotes (Bundle) que já contemplam o NetBeans, o servidor de aplicação GlassFish e os plugins para sua interface RAD (Desktop com Java Swing, Java FX e Web).

NetBeans History: https://netbeans.org/about/history.html

C#

Microsoft já namorava o arquiteto por trás do Delphi e de seu predecessor Turbo Pascal foi Anders Hejlsberg, onde se tornou o arquiteto responsável pelo projeto do C# e foi peça chave na criação do ambiente Microsoft .NET. Então é de se supor que o C# leva um pouco do Delphi dentro de si e podemos ver isto claramente na sintaxe de algumas instruções, principalmente no que se refere ao conceito de Eventos (Sender) e Setter (Getter e Setter).

C# Language: http://msdn.microsoft.com/pt-br/library/z1zx9t92.aspx

Métodos Getter e Setter

Em Java, C++ e C# existe o conceito de Getter e Setter  (inclusive sintaxe idênticas) para métodos de classe que em Delphi seria “equivalente” a uma Function e uma Procedure. Java e C++ seguem o padrão comum para o método Setter, em C# a Microsoft ensina o conceito como do Java quando você cria uma classe, o Visual Studio possui um atalho para criar Getter e Setter automaticamente mas não utilizando métodos, assim como os objetos do framework usam a sintaxe do Delphi, embutindo o conceito de Getter e Setter dentro de uma propriedade ou seja um método Getter para Java e C++, exemplo:

Getter e Setter  – Java: http://docs.oracle.com/javaee/6/tutorial/doc/gjbbp.html

Getter e Setter – C#: http://msdn.microsoft.com/en-us/library/w86s7x04.aspx

Então em C# é possível utilizar o conceito comum de Getter e Setter baseado em C++ e Java, utilizar o conceito de Get e Set embutido dentro de um método Getter (propriedades em C#) é meramente opcional e apenas uma questão de sintaxe do objeto, no qual desenvolvedores Delphi estão bem familiarizados. Inclusive o conceito propriedades nos objetos C#, torna a IDE do Visual Studio, na questão pratica do ponto de vista do desenvolvedor muito similar a IDE do Delphi.

Delphi Properties: http://docwiki.embarcadero.com/RADStudio/XE3/en/Properties

Código Fonte Java e C#


// Java

Objeto.setVisible(True); // Setter

// C# e Delphi (Propriedades)

Objeto.Visible = True; // Setter porem igual ao Delphi*

// * O conceito de operadores Java e C# são iguais
//   Delphi usa := para atribuir um valor

Eventos – Windows (Win32) – Java – C#

Outra similaridade do C# com o Delphi são os eventos, o conceito de eventos do Windows a grosso modo é uma fila de mensagens que pode ser utilizado pela API através da função WindowProc ou WndProc e é mais similar ao Java que utiliza tipos de mensagens implementadas na classe (ActionListener, ItemListener, MouseListner e outros) por exemplo, o Java possui um ActionListner que identifica o evento de  clique de qualquer botão independente da quantidade de botões em um formulário utilizando apenas um método, já o C# assim como Delphi e a IDE RAD do NETBEANS para JAVA tornam está funcionalidade mais fácil porem geram um código maior criando um evento de clique para cada botão da tela.

WindowProc: http://msdn.microsoft.com/pt-br/library/ms633573.aspx

Windows Messages: http://msdn.microsoft.com/pt-br/library/ms644927.aspx

Java Event Listner: http://docs.oracle.com/javase/tutorial/uiswing/events/intro.html

C# Event Handler: http://msdn.microsoft.com/en-us/library/system.eventhandler(v=vs.110).aspx

Assim, você pode testemunhar a “semelhança” do conceito de Object Sender entre Delphi e o .Net Framework (VB.NET e C#), utilize os links abaixo para entender a sintaxe final do evento de clique de um botão.

Object Sender Delphi: http://docwiki.embarcadero.com/RADStudio/XE4/en/Using_the_Sender_Parameter

Object Sender .NET Framework: http://msdn.microsoft.com/en-us/library/aa457091.aspx

Soluções e Projetos

Um ponto muito importante no desenvolvimento para o C# (Java já utilizava o Apache Ant e soluções recentes utilizam o Apache Maven) é que a Microsoft sabia da dificuldade de muitos programadores em utilizar o conceito Win32 na arquitetura do software e estruturação do código fonte, então o que em Delphi exigia abrir um projeto tipo Dll (não gerenciado) escrever uma biblioteca adequada, importar as funções para seu projeto principal e assim por diante. No Visual Studio surgiu o conceito de solução, que unido a um ambiente gerenciado torna possível criar vários projetos por solução,  onde o projeto principal contendo um Windows Form,  por exemplo gera um executável e os projetos desta solução contendo apenas biblioteca de classes geram automaticamente uma Dll (ambiente gerenciado) que é referenciada ao projeto principal e esta resolvido o problema que possuíamos no Delphi de alguns desenvolvedores criando executáveis enormes e códigos redundantes.

Solution and Project Basics: http://msdn.microsoft.com/en-us/library/b142f8e7.aspx

Concluindo

Vale a pena migrar para uma linguagem mais moderna sempre, inovação faz parte da área de software, todos nós só temos a ganhar, melhores ferramentas, técnicas mais modernas, maior produtividade, o importante é avaliar caso a caso e criar um projeto consistente e na medida para que este processo se realize da melhor maneira possível.

O que vimos neste post é apenas uma primeira visão da importância do Delphi e como o Delphi influenciou outras linguagens de programação. Para uma comparação mais precisa é necessário um projeto bem elaborado e fica a mensagem de que o Delphi  pode ter desaparecido da grande mídia mas continuará vivo por muito tempo.

Em C++ MFC não existe um componente pronto para fazer o trabalho de redimensionamento de painéis, mas existe uma classe que encapsula a API do Windows que faz exatamente este trabalho e esta classe é  chamada de CSplitterWnd, a classe fornece a funcionalidade de uma janela de divisão, que é uma janela que contém vários painéis. Um objeto CSplitterWnd geralmente é incorporado em um CFrameWnd pai ou um objeto filho CMDIChildWnd, isto significa que esta classe utiliza um tipo de aplicação MDI e não uma aplicação baseada em diálogos.

É possível criar um workaround que utiliza um componente estático Picture Control para criar um Splitter que redimensiona os componentes e não painéis como faz a classe CSplitterWnd. Existe vários componentes prontos na internet para fazer isto, mas nós vamos utilizar uma classe de código aberto para fazer este trabalho.

Splitter Control

Splitter Control

 

Visual Studio

Vamos utilizar a classe CSplitterControl que é Open Source que você encontra logo abaixo:

  1. Crie um projeto MFC Dialog Based.
  2. Coloque na tela dois componentes Picture Control e nomeie um como IDC_IMAGEM e outro como IDC_SPLITTER1.
  3. Coloque um componente Edit Control e crie uma variável chamada m_texto;
  4. No componente IDC_IMAGEM mude sua propriedade Type para Bitmap.
  5. No componente IDC_SPLITTER1 mude sua propriedade Visible para False.
  6. No componente Edit Control mude sua propriedade MultiLines para True.
  7. Disponha os componentes como na imagem abaixo:

    Splitter Control - Design

    Splitter Control – Design

  8. Adicione a classe CSplitterControl em seu projeto.
  9. Efetue o Download da imagem e a transforme em BMP, você pode usar o Paint Brush do Windows: https://desenvolvimentoaberto.files.wordpress.com/2014/04/balonismo.jpg
  10. Copie os trechos marcados do código abaixo para seu código gerado automaticamente.

 

Exemplo:

Neste exemplo utilizamos uma classe Open Source Splitter Control para criar um Splitter à partir de um componente Picture Control que controla o tamanho dos componentes entre eles controlando seu tamanho baseado no valor do Splitter.

Obs: Lembre-se que os exemplos abaixo utilizam classes e as classes em C++ são divididas em dois arquivos.

C++

Porgrama – Classe meusplittercpp.h

// código gerado automaticamente
// meusplittercppDlg.h : header file
//

#pragma once
#include "afxwin.h"
#include "SplitterControl.h"

class CmeusplittercppDlg : public CDialogEx
{

public:
	CmeusplittercppDlg(CWnd* pParent = NULL);	

	enum { IDD = IDD_MEUSPLITTERCPP_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	

	// Desenvolvimento Aberto
	virtual LRESULT DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam);

protected:
	HICON m_hIcon;

	// Desenvolvimento Aberto
	void Redimensiona(int delta);
	void Append(CString texto);
	CSplitterControl m_wndSplitter1;
	// ******

	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:

	CEdit m_texto;
};

Porgrama – Classe meusplittercpp.cpp


// meusplittercppDlg.cpp : implementation file
//

#include "stdafx.h"
#include "meusplittercpp.h"
#include "meusplittercppDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// CmeusplittercppDlg dialog

CmeusplittercppDlg::CmeusplittercppDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CmeusplittercppDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CmeusplittercppDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_EDIT1, m_texto);
}

BEGIN_MESSAGE_MAP(CmeusplittercppDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
//	ON_WM_CREATE()
END_MESSAGE_MAP()

// CmeusplittercppDlg message handlers

BOOL CmeusplittercppDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	SetIcon(m_hIcon, TRUE);
	SetIcon(m_hIcon, FALSE);		

	// Desenvolvimento Aberto
	// Inicializa componentes

	// Adiciona texto
	Append(L"O balonismo é um esporte aeronáutico praticado com um balão de ar quente.\n");
	Append(L"Possui adeptos em todo o mundo. No Brasil, o esporte começou a se popularizar\n");
	Append(L"a partir dos anos 90.\n");
	Append(L"O balão é considerado uma aeronave assim como avião, helicópteros e outros.\n");
	Append(L"Por esta razão o balão deve ter uma matricula (prefixo) registrado junto\n");
	Append(L"à ANAC, seu piloto deve possuir uma licença (brevê) específico para a pratica\n");
	Append(L"do balonismo também emitido pela ANAC.");

	// Cria componente Splitter Control baseado no componente Picture Control
	CRect rc;
	CWnd* pWnd;

	pWnd = GetDlgItem(IDC_SPLITTER1);
	pWnd->GetWindowRect(rc);
	ScreenToClient(rc);
	m_wndSplitter1.Create(WS_CHILD | WS_VISIBLE, rc, this, IDC_SPLITTER1);
	m_wndSplitter1.SetRange(50, 50, -1);

	// Carrega imagem

	CStatic * foto;
	CString imagem;

	foto = (CStatic *)GetDlgItem(IDC_IMAGEM);

	imagem = L"C:/Desenvolvimento Aberto/balonismo.bmp";

	HBITMAP pic = (HBITMAP)LoadImage(NULL, imagem, IMAGE_BITMAP,370, 260, LR_LOADFROMFILE);
	foto->SetBitmap(pic);

	// ***

	return TRUE;
}

void CmeusplittercppDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); 

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

HCURSOR CmeusplittercppDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

// Desenvolvimento Aberto
// Nosso código começa aqui

LRESULT CmeusplittercppDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	if (message == WM_NOTIFY)
	{
		if (wParam == IDC_SPLITTER1)
		{
			SPC_NMHDR* pHdr = (SPC_NMHDR*)lParam;
			Redimensiona(pHdr->delta);
		}
	}

	return CDialog::DefWindowProc(message, wParam, lParam);
}

void CmeusplittercppDlg::Redimensiona(int delta)
{
	CSplitterControl::ChangeWidth(GetDlgItem(IDC_IMAGEM), delta);
	CSplitterControl::ChangeWidth(&m_texto, -delta, CW_RIGHTALIGN);

	Invalidate();
	UpdateWindow();
}

void CmeusplittercppDlg::Append(CString texto)
{
	int tam1 = m_texto.GetWindowTextLengthW();
	m_texto.SetSel(tam1, tam1);
	m_texto.ReplaceSel(texto);

}

Splitter Control – Componente Open Source

Porgrama – Classe CSplitterControl.h

/**************CSplitterControl interface***********
*	Class name :CSplitterControl
*	Purpose: Implement splitter control for dialog
*			or any other windows.
*	Author: Nguyen Huy Hung, Vietnamese student.
*	Date:	May 29th 2002.
*	Note: You can use it for any purposes. Feel free
*			to change, modify, but please do not
*			remove this.
*	No warranty of any risks.
*	(:-)
*/
#if !defined(AFX_SPLITTERCONTROL_H__FEBBA242_B2C9_4403_B68D_E519D645CB15__INCLUDED_)
#define AFX_SPLITTERCONTROL_H__FEBBA242_B2C9_4403_B68D_E519D645CB15__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// SplitterControl.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CSplitterControl window
#define SPN_SIZED WM_USER + 1
#define CW_LEFTALIGN 1
#define CW_RIGHTALIGN 2
#define CW_TOPALIGN 3
#define CW_BOTTOMALIGN 4
#define SPS_VERTICAL 1
#define SPS_HORIZONTAL 2
typedef struct SPC_NMHDR
{
	NMHDR hdr;
	int delta;
} SPC_NMHDR;

class CSplitterControl : public CStatic
{
// Construction
public:
	CSplitterControl();

// Attributes
public:
protected:
	BOOL		m_bIsPressed;
	int			m_nType;
	int			m_nX, m_nY;
	int			m_nMin, m_nMax;
	int			m_nSavePos;		// Save point on the lbutton down
								// message
// Operations
public:

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CSplitterControl)
	//}}AFX_VIRTUAL

// Implementation
public:
	static void ChangePos(CWnd* pWnd, int dx, int dy);
	static void ChangeWidth(CWnd* pWnd, int dx, DWORD dwFlag = CW_LEFTALIGN);
	static void ChangeHeight(CWnd* pWnd, int dy, DWORD dwFlag = CW_TOPALIGN);
public:
	void		SetRange(int nMin, int nMax);
	void		SetRange(int nSubtraction, int nAddition, int nRoot);

	int			GetStyle();
	int			SetStyle(int nStyle = SPS_VERTICAL);
	void		Create(DWORD dwStyle, const CRect& rect, CWnd* pParent, UINT nID);
	virtual		~CSplitterControl();

	// Generated message map functions
protected:
	virtual void	DrawLine(CDC* pDC, int x, int y);
	void			MoveWindowTo(CPoint pt);
	//{{AFX_MSG(CSplitterControl)
	afx_msg void	OnPaint();
	afx_msg void	OnMouseMove(UINT nFlags, CPoint point);
	afx_msg BOOL	OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
	afx_msg void	OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void	OnLButtonUp(UINT nFlags, CPoint point);
	//}}AFX_MSG

	DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_SPLITTERCONTROL_H__FEBBA242_B2C9_4403_B68D_E519D645CB15__INCLUDED_)

Porgrama – Classe CSplitterControl.cpp

// SplitterControl.cpp : implementation file
//

#include "stdafx.h"
#include "SplitterControl.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CSplitterControl

// hCursor1 is for vertiacal one
// and hCursor2 is for horizontal one
static HCURSOR SplitterControl_hCursor1 = NULL;
static HCURSOR SplitterControl_hCursor2 = NULL;

CSplitterControl::CSplitterControl()
{
	// Mouse is pressed down or not ?
	m_bIsPressed = FALSE;	

	// Min and Max range of the splitter.
	m_nMin = m_nMax = -1;
}

CSplitterControl::~CSplitterControl()
{
}

BEGIN_MESSAGE_MAP(CSplitterControl, CStatic)
	//{{AFX_MSG_MAP(CSplitterControl)
	ON_WM_PAINT()
	ON_WM_MOUSEMOVE()
	ON_WM_SETCURSOR()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSplitterControl message handlers

/****************************************************
*	Create(DWORD dwStyle, const CRect& rect, CWnd* pParent, nID)
*	Use this function instead of the CStatic::Create function
* Parameters: No need to explain (see MSDN (:-) )
*
****************************************************/
void CSplitterControl::Create(DWORD dwStyle, const CRect &rect, CWnd *pParent, UINT nID)
{
	CRect rc = rect;
	dwStyle |= SS_NOTIFY;

	// Determine default type base on it's size.
	m_nType = (rc.Width() < rc.Height())?
					SPS_VERTICAL:
					SPS_HORIZONTAL;

	if (m_nType == SPS_VERTICAL)
		rc.right = rc.left + 5;
	else // SPS_HORIZONTAL
		rc.bottom = rc.top + 5;

	CStatic::Create(L"", dwStyle, rc, pParent, nID);

	if (!SplitterControl_hCursor1)
	{
		SplitterControl_hCursor1 = AfxGetApp()->LoadStandardCursor(IDC_SIZEWE);
		SplitterControl_hCursor2 = AfxGetApp()->LoadStandardCursor(IDC_SIZENS);
	}

	// force the splitter not to be splited.
	SetRange(0, 0, -1);
}

// Set style for splitter control
// nStyle = SPS_VERTICAL or SPS_HORIZONTAL
int CSplitterControl::SetStyle(int nStyle)
{
	int m_nOldStyle = m_nType;
	m_nType = nStyle;
	return m_nOldStyle;
}
int CSplitterControl::GetStyle()
{
	return m_nType;
}

void CSplitterControl::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	CRect rcClient;
	GetClientRect(rcClient);

	CBrush br, *pOB;
	CPen pen, *pOP;

	dc.Draw3dRect(rcClient, GetSysColor(COLOR_BTNHIGHLIGHT), GetSysColor(COLOR_BTNSHADOW));
	rcClient.DeflateRect(1,1,1,1);

	pen.CreatePen(0, 1, RGB(200, 200, 200));
	br.CreateSolidBrush(RGB(200, 220, 220));
	pOB = dc.SelectObject(&br);
	pOP = dc.SelectObject(&pen);

	dc.Rectangle(rcClient);

	// Restore pen and brush
	DeleteObject(dc.SelectObject(pOB));
	DeleteObject(dc.SelectObject(pOP));
}

void CSplitterControl::OnMouseMove(UINT nFlags, CPoint point)
{
	if (m_bIsPressed)
	{
		CWindowDC dc(NULL);
		DrawLine(&dc, m_nX, m_nY);

		CPoint pt = point;
		ClientToScreen(&pt);
		GetParent()->ScreenToClient(&pt);

		if (pt.x < m_nMin)
			pt.x = m_nMin;
		if (pt.y < m_nMin)
			pt.y = m_nMin;

		if (pt.x > m_nMax)
			pt.x = m_nMax;
		if (pt.y > m_nMax)
			pt.y = m_nMax;

		GetParent()->ClientToScreen(&pt);
		m_nX = pt.x;
		m_nY = pt.y;
		DrawLine(&dc, m_nX, m_nY);
	}
	CStatic::OnMouseMove(nFlags, point);
}

BOOL CSplitterControl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
	if (nHitTest == HTCLIENT)
	{
		(m_nType == SPS_VERTICAL)?(::SetCursor(SplitterControl_hCursor1))
			:(::SetCursor(SplitterControl_hCursor2));
		return 0;
	}
	else
		return CStatic::OnSetCursor(pWnd, nHitTest, message);
}

void CSplitterControl::OnLButtonDown(UINT nFlags, CPoint point)
{
	CStatic::OnLButtonDown(nFlags, point);

	m_bIsPressed = TRUE;
	SetCapture();
	CRect rcWnd;
	GetWindowRect(rcWnd);

	if (m_nType == SPS_VERTICAL)
		m_nX = rcWnd.left + rcWnd.Width() / 2;	

	else
		m_nY = rcWnd.top  + rcWnd.Height() / 2;

	if (m_nType == SPS_VERTICAL)
		m_nSavePos = m_nX;
	else
		m_nSavePos = m_nY;

	CWindowDC dc(NULL);
	DrawLine(&dc, m_nX, m_nY);
}

void CSplitterControl::OnLButtonUp(UINT nFlags, CPoint point)
{
	if (m_bIsPressed)
	{
		ClientToScreen(&point);
		CWindowDC dc(NULL);

		DrawLine(&dc, m_nX, m_nY);
		CPoint pt(m_nX, m_nY);
		m_bIsPressed = FALSE;
		CWnd *pOwner = GetOwner();
		if (pOwner && IsWindow(pOwner->m_hWnd))
		{
			CRect rc;
			int delta;
			pOwner->GetClientRect(rc);
			pOwner->ScreenToClient(&pt);
			MoveWindowTo(pt);

			if (m_nType == SPS_VERTICAL)
				delta = m_nX - m_nSavePos;
			else
				delta = m_nY - m_nSavePos;

			SPC_NMHDR nmsp;

			nmsp.hdr.hwndFrom = m_hWnd;
			nmsp.hdr.idFrom   = GetDlgCtrlID();
			nmsp.hdr.code     = SPN_SIZED;
			nmsp.delta = delta;

			pOwner->SendMessage(WM_NOTIFY, nmsp.hdr.idFrom, (LPARAM)&nmsp);
		}
	}

	CStatic::OnLButtonUp(nFlags, point);
	ReleaseCapture();
}

void CSplitterControl::DrawLine(CDC* pDC, int x, int y)
{
	int nRop = pDC->SetROP2(R2_NOTXORPEN);

	CRect rcWnd;
	int d = 1;
	GetWindowRect(rcWnd);
	CPen  pen;
	pen.CreatePen(0, 1, RGB(200, 200, 200));
	CPen *pOP = pDC->SelectObject(&pen);

	if (m_nType == SPS_VERTICAL)
	{
		pDC->MoveTo(m_nX - d, rcWnd.top);
		pDC->LineTo(m_nX - d, rcWnd.bottom);

		pDC->MoveTo(m_nX + d, rcWnd.top);
		pDC->LineTo(m_nX + d, rcWnd.bottom);
	}
	else // m_nType == SPS_HORIZONTAL
	{
		pDC->MoveTo(rcWnd.left, m_nY - d);
		pDC->LineTo(rcWnd.right, m_nY - d);

		pDC->MoveTo(rcWnd.left, m_nY + d);
		pDC->LineTo(rcWnd.right, m_nY + d);
	}
	pDC->SetROP2(nRop);
	pDC->SelectObject(pOP);
}

void CSplitterControl::MoveWindowTo(CPoint pt)
{
	CRect rc;
	GetWindowRect(rc);
	CWnd* pParent;
	pParent = GetParent();
	if (!pParent || !::IsWindow(pParent->m_hWnd))
		return;

	pParent->ScreenToClient(rc);
	if (m_nType == SPS_VERTICAL)
	{
		int nMidX = (rc.left + rc.right) / 2;
		int dx = pt.x - nMidX;
		rc.OffsetRect(dx, 0);
	}
	else
	{
		int nMidY = (rc.top + rc.bottom) / 2;
		int dy = pt.y - nMidY;
		rc.OffsetRect(0, dy);
	}
	MoveWindow(rc);
}

void CSplitterControl::ChangeWidth(CWnd *pWnd, int dx, DWORD dwFlag)
{
	CWnd* pParent = pWnd->GetParent();
	if (pParent && ::IsWindow(pParent->m_hWnd))
	{
		CRect rcWnd;
		pWnd->GetWindowRect(rcWnd);
		pParent->ScreenToClient(rcWnd);
		if (dwFlag == CW_LEFTALIGN)
			rcWnd.right += dx;
		else if (dwFlag == CW_RIGHTALIGN)
			rcWnd.left -= dx;
		pWnd->MoveWindow(rcWnd);
	}
}

void CSplitterControl::ChangeHeight(CWnd *pWnd, int dy, DWORD dwFlag)
{
	CWnd* pParent = pWnd->GetParent();
	if (pParent && ::IsWindow(pParent->m_hWnd))
	{
		CRect rcWnd;
		pWnd->GetWindowRect(rcWnd);
		pParent->ScreenToClient(rcWnd);
		if (dwFlag == CW_TOPALIGN)
			rcWnd.bottom += dy;
		else if (dwFlag == CW_BOTTOMALIGN)
			rcWnd.top -= dy;
		pWnd->MoveWindow(rcWnd);
	}
}

void CSplitterControl::ChangePos(CWnd* pWnd, int dx, int dy)
{
	CWnd* pParent = pWnd->GetParent();
	if (pParent && ::IsWindow(pParent->m_hWnd))
	{
		CRect rcWnd;
		pWnd->GetWindowRect(rcWnd);
		pParent->ScreenToClient(rcWnd);
		rcWnd.OffsetRect(-dx, dy);

		pWnd->MoveWindow(rcWnd);
	}
}

void CSplitterControl::SetRange(int nMin, int nMax)
{
	m_nMin = nMin;
	m_nMax = nMax;
}

// Set splitter range from (nRoot - nSubtraction) to (nRoot + nAddition)
// If (nRoot < 0)
//		nRoot =  <current position of the splitter>
void CSplitterControl::SetRange(int nSubtraction, int nAddition, int nRoot)
{
	if (nRoot < 0)
	{
		CRect rcWnd;
		GetWindowRect(rcWnd);
		if (m_nType == SPS_VERTICAL)
			nRoot = rcWnd.left + rcWnd.Width() / 2;
		else // if m_nType == SPS_HORIZONTAL
			nRoot = rcWnd.top + rcWnd.Height() / 2;
	}
	m_nMin = nRoot - nSubtraction;
	m_nMax = nRoot + nAddition;
}

SAP Container é um controle que acomoda outros controles, como o SAP Tree,  o SAP Picture , 0 SAP TextEdit , e assim por diante. Ele gerencia esses controles logicamente em uma coleção, e fornece uma área física em que eles são exibidos. Existem cinco tipos de SAP Containers.

CL_GUI_SPLITTER_CONTAINER

Representa um controle que consiste de uma barra móvel que divide a área de exibição de um recipiente em dois painéis redimensionáveis​​. Permite exibir mais de um controle em uma determinada área, dividindo-o nas células.

CL_GUI_CONTAINER

Representa um painel que pode ser alocado dentro de uma célula de um container.

Sap Container

Sap Container

Screen Painter

Para usar o Sap Container no modo Splitter siga os seguintes passos:

  1. Crie um programa chamado ZSPLITERCONTAINER na transação SE38.
  2. Você pode criar um titulo e um menu para este programa na transação SE41 (Opcional).
  3. Crie uma tela de numero 100 para este programa no Screen Painter na transação SE51.
  4. Crie um evento PBO padrão para a variável Status 100 na aba Flow Logic.
  5. Em Layout coloque um componente Custom Control na tela e o nomeie como MEUCONTAINER.
  6. Ative a tela 100.
  7. Abra seu programa  e utilize o código abaixo.

Exemplo:

Neste exemplo criamos uma tela  à partir de um componente visual Custom Control que possui um painel contendo duas células redimensionáveis, cada uma contendo um painel que contem um outro componente Custom instanciado de um objeto.

Abap

*&---------------------------------------------------------------------*
*& Report  ZSPLITERCONTAINER
*&
*&---------------------------------------------------------------------*
*& Desenvolvimento Aberto
*& SAP Container - Splitter
*&---------------------------------------------------------------------*

REPORT  ZSPLITERCONTAINER.

* Declara componentes
DATA: meucontainer TYPE REF TO cl_gui_custom_container,
      painel       TYPE REF TO CL_GUI_SPLITTER_CONTAINER,
      imagem       TYPE REF TO CL_GUI_PICTURE,
      editor       TYPE REF TO cl_gui_textedit,
      painel1      TYPE REF TO CL_GUI_CONTAINER,
      painel2      TYPE REF TO CL_GUI_CONTAINER.

* Declara tabela interna
DATA: linha(256),
      texto_tab LIKE STANDARD TABLE OF linha.
           
* Inicio do programa
START-OF-SELECTION.

* Adiciona texto na tabela interna
linha = 'O balonismo é um esporte aeronáutico praticado com um balão de ar quente.'.
APPEND linha TO texto_tab.
linha = 'Possui adeptos em todo o mundo. No Brasil, o esporte começou a se popularizar'.
APPEND linha TO texto_tab.
linha = 'a partir dos anos 90.'.
APPEND linha TO texto_tab.
linha = 'O balão é considerado uma aeronave assim como avião, helicópteros e outros.'.
APPEND linha TO texto_tab.
linha = 'Por esta razão o balão deve ter uma matricula (prefixo) registrado junto'.
APPEND linha TO texto_tab.
linha = 'à ANAC, seu piloto deve possuir uma licença (brevê) específico para a pratica'.
APPEND linha TO texto_tab.
linha = 'do balonismo também emitido pela ANAC.'.
APPEND linha TO texto_tab.

* Chama tela Screen Painter
CALL SCREEN 100.

* Modulo PBO
MODULE STATUS_0100 OUTPUT.
*  SET PF-STATUS 'xxxxxxxx'.
*  SET TITLEBAR 'xxx'.

* Cria componentes

* Cria componente Screen Painter Custom Container
  CREATE OBJECT MEUCONTAINER
    EXPORTING
      CONTAINER_NAME = 'MEUCONTAINER'
      LIFETIME       = MEUCONTAINER->LIFETIME_DYNPRO.

* Cria Splitter Container
  CREATE OBJECT PAINEL
    EXPORTING
      PARENT  = MEUCONTAINER
      ROWS    = 1
      COLUMNS = 2
      ALIGN   = 15.

* Exibe Painel 1
  CALL METHOD PAINEL->GET_CONTAINER
    EXPORTING
      ROW       = 1
      COLUMN    = 1
    RECEIVING
      CONTAINER = PAINEL1.

* Exibe Painel 2
  CALL METHOD PAINEL->GET_CONTAINER
    EXPORTING
      ROW       = 1
      COLUMN    = 2
    RECEIVING
      CONTAINER = PAINEL2.

* Cria imagem
  CREATE OBJECT IMAGEM
    EXPORTING
      LIFETIME = IMAGEM->LIFETIME_DYNPRO
      PARENT   = PAINEL1.

*Chama imagem da url
  CALL METHOD IMAGEM->load_picture_from_url
    EXPORTING
      url   = 'https://desenvolvimentoaberto.files.wordpress.com/2014/04/balonismo.jpg'
    EXCEPTIONS
      error = 1.

* Cria Editor
  CREATE OBJECT EDITOR
    EXPORTING
      PARENT = PAINEL2.

* Adiciona texto
  CALL METHOD editor->set_text_as_stream
    EXPORTING
      text = texto_tab.

ENDMODULE.                 " STATUS_0100  OUTPUT

Painel deslizante é um componente da interface gráfica que permite que o usuário redimensione componentes contidos normalmente dentro de dois painéis que podem ser posicionados na horizontal ou na vertical.

PanedWindow

O PanedWindow  é um widget gerenciador de geometria, que pode conter um ou mais widgets filhos (“painéis”). Os widgets filhos pode ser redimensionados pelo usuário, ao mover linhas de separação (“sashes“) usando o mouse.

PanedWindow

PanedWindow

Exemplo:

Neste exemplo criamos um painel de rolagem divido na horizontal que contem dois componentes que podem ser redimensionados pelo usuário, respeitando o tamanho mínimo de cada componente.

Python

#!/usr/bin/env python
# -*- coding: latin-1 -*-
# Desenvolvimento Aberto
# Panewindow.py

# importa modulos
from Tkinter import *
from PIL import Image, ImageTk
from ScrolledText import ScrolledText
import urllib2 as urllib
import cStringIO

# Cria formulario
formulario = Tk()
formulario.title = "Desenvolvimento Aberto"

# Declara variavel
txt = "O balonismo e um esporte aeronautico praticado com um balao de ar quente.\n" + \
      "Possui adeptos em todo o mundo. No Brasil, o esporte comecou a se popularizar\n" + \
      "a partir dos anos 90.\n" + \
      "O balão é considerado uma aeronave assim como aviao, helicopteros e outros.\n" + \
      "Por esta razao o balao deve ter uma matricula (prefixo) registrado junto\n" + \
      "a ANAC, seu piloto deve possuir uma licenca (breve) especifico para a pratica\n" + \
      "do balonismo tambem emitido pela ANAC.";
 
# Cria Url
url = urllib.urlopen("https://desenvolvimentoaberto.files.wordpress.com/2014/04/balonismo.jpg")

# Lê imagem da url
figura = cStringIO.StringIO(url.read())

# carrega a imagem
imagem = Image.open(figura)

# joga a imagem para o componente
foto = ImageTk.PhotoImage(imagem)

painel = PanedWindow(orient=HORIZONTAL)
painel.pack(fill=BOTH, expand=10)

# Exibi a imagem
pic = Label(painel, image = foto)

# Cria caixa de texto
texto = ScrolledText(painel, height =10, width = 40)
texto.insert(END, txt)

# Adiciona componentes no painel
painel.add(pic)
painel.add(texto)

# Loop do tcl
mainloop()

Visual – SplitContainer – C#

Publicado: 25 de abril de 2014 em C#

Painel deslizante é um componente da interface gráfica que permite que o usuário redimensione componentes contidos normalmente dentro de dois painéis que podem ser posicionados na horizontal ou na vertical.

SplitContainer

Representa um controle que consiste de uma barra móvel que divide a área de exibição de um recipiente em dois painéis redimensionáveis​​.

SplitContainer

SplitContainer

Exemplo:

Neste exemplo criamos um painel de rolagem divido na horizontal que contem dois componentes que podem ser redimensionados pelo usuário, respeitando o tamanho mínimo de cada componente.

C#

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 paineldeslizante
{
    public partial class Form1 : Form
    {
        // Declara componentes
        SplitContainer painel;
        PictureBox imagem;
        RichTextBox area;

        // Declara variaveis
        String txt = "O balonismo é um esporte aeronáutico praticado com um balão de ar quente.\n" +
                     "Possui adeptos em todo o mundo. No Brasil, o esporte começou a se popularizar\n" +
                     "a partir dos anos 90.\n" +
                     "O balão é considerado uma aeronave assim como avião, helicópteros e outros.\n" +
                     "Por esta razão o balão deve ter uma matricula (prefixo) registrado junto\n" +
                     "à ANAC, seu piloto deve possuir uma licença (brevê) específico para a pratica\n" +
                     "do balonismo também emitido pela ANAC.";

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            // Define propriedades do formulario
            this.Text = "DA - Painel Deslizante";
            this.Size = new Size(500, 300);

            // Cria componentes
            painel = new SplitContainer();
            imagem = new PictureBox();
            area = new RichTextBox();

            // Define tamanho minimo dos componentes
            imagem.MinimumSize = new Size(200, 100);
            area.MinimumSize = new Size(200, 100);

            // Define texto
            area.Text = txt;
            
            // Define limites dos componentes
            painel.Dock = DockStyle.Fill;
            imagem.Dock = DockStyle.Fill;
            area.Dock = DockStyle.Fill;
                      
            // Carrega imagem da internet
            imagem.ImageLocation = "https://desenvolvimentoaberto.files.wordpress.com/2014/04/balonismo.jpg";
            imagem.SizeMode = PictureBoxSizeMode.CenterImage;

            // Adiciona paineis no container
            painel.Panel1.Controls.Add(imagem);
            painel.Panel2.Controls.Add(area);

            // Adiciona painel ao formulario
            this.Controls.Add(painel);

        }
        
    }
}